forge-openclaw-plugin 0.2.3 → 0.2.7

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 (117) hide show
  1. package/README.md +114 -6
  2. package/dist/assets/board-CzgvdLO8.js +6 -0
  3. package/dist/assets/board-CzgvdLO8.js.map +1 -0
  4. package/dist/assets/favicon-BCHm9dUV.ico +0 -0
  5. package/dist/assets/index-8d_oM8fL.js +27 -0
  6. package/dist/assets/index-8d_oM8fL.js.map +1 -0
  7. package/dist/assets/index-D4A_bq8m.css +1 -0
  8. package/dist/assets/motion-STUd1O46.js +10 -0
  9. package/dist/assets/motion-STUd1O46.js.map +1 -0
  10. package/dist/assets/plus-jakarta-sans-latin-ext-wght-normal-DmpS2jIq.woff2 +0 -0
  11. package/dist/assets/plus-jakarta-sans-latin-wght-normal-eXO_dkmS.woff2 +0 -0
  12. package/dist/assets/plus-jakarta-sans-vietnamese-wght-normal-qRpaaN48.woff2 +0 -0
  13. package/dist/assets/sora-latin-ext-wght-normal-CawQDOvP.woff2 +0 -0
  14. package/dist/assets/sora-latin-wght-normal-DdqRvwsR.woff2 +0 -0
  15. package/dist/assets/space-grotesk-latin-500-normal-CNSSEhBt.woff +0 -0
  16. package/dist/assets/space-grotesk-latin-500-normal-lFbtlQH6.woff2 +0 -0
  17. package/dist/assets/space-grotesk-latin-700-normal-CwsQ-cCU.woff +0 -0
  18. package/dist/assets/space-grotesk-latin-700-normal-RjhwGPKo.woff2 +0 -0
  19. package/dist/assets/space-grotesk-latin-ext-500-normal-3dgZTiw9.woff +0 -0
  20. package/dist/assets/space-grotesk-latin-ext-500-normal-DUe3BAxM.woff2 +0 -0
  21. package/dist/assets/space-grotesk-latin-ext-700-normal-BQnZhY3m.woff2 +0 -0
  22. package/dist/assets/space-grotesk-latin-ext-700-normal-HVCqSBdx.woff +0 -0
  23. package/dist/assets/space-grotesk-vietnamese-500-normal-BTqKIpxg.woff +0 -0
  24. package/dist/assets/space-grotesk-vietnamese-500-normal-BmEvtly_.woff2 +0 -0
  25. package/dist/assets/space-grotesk-vietnamese-700-normal-DMty7AZE.woff2 +0 -0
  26. package/dist/assets/space-grotesk-vietnamese-700-normal-Duxec5Rn.woff +0 -0
  27. package/dist/assets/table-CtNlETLc.js +23 -0
  28. package/dist/assets/table-CtNlETLc.js.map +1 -0
  29. package/dist/assets/ui-ThzkR_oW.js +46 -0
  30. package/dist/assets/ui-ThzkR_oW.js.map +1 -0
  31. package/dist/assets/vendor-CRS-psbw.css +1 -0
  32. package/dist/assets/vendor-DyHAI6nk.js +423 -0
  33. package/dist/assets/vendor-DyHAI6nk.js.map +1 -0
  34. package/dist/assets/viz-BJuBCz_G.js +34 -0
  35. package/dist/assets/viz-BJuBCz_G.js.map +1 -0
  36. package/dist/favicon.ico +0 -0
  37. package/dist/favicon.png +0 -0
  38. package/dist/index.html +29 -0
  39. package/dist/openclaw/api-client.d.ts +8 -0
  40. package/dist/openclaw/api-client.js +31 -4
  41. package/dist/openclaw/local-runtime.d.ts +3 -0
  42. package/dist/openclaw/local-runtime.js +135 -0
  43. package/dist/openclaw/parity.d.ts +4 -4
  44. package/dist/openclaw/parity.js +23 -33
  45. package/dist/openclaw/plugin-entry-shared.d.ts +5 -3
  46. package/dist/openclaw/plugin-entry-shared.js +52 -10
  47. package/dist/openclaw/routes.d.ts +12 -3
  48. package/dist/openclaw/routes.js +156 -924
  49. package/dist/openclaw/tools.js +242 -1100
  50. package/dist/server/app.js +2450 -0
  51. package/dist/server/db.js +313 -0
  52. package/dist/server/e2e-server.js +20 -0
  53. package/dist/server/errors.js +15 -0
  54. package/dist/server/index.js +16 -0
  55. package/dist/server/managers/base.js +17 -0
  56. package/dist/server/managers/contracts.js +47 -0
  57. package/dist/server/managers/platform/api-gateway-manager.js +11 -0
  58. package/dist/server/managers/platform/audit-manager.js +15 -0
  59. package/dist/server/managers/platform/authentication-manager.js +56 -0
  60. package/dist/server/managers/platform/authorization-manager.js +56 -0
  61. package/dist/server/managers/platform/background-job-manager.js +10 -0
  62. package/dist/server/managers/platform/configuration-manager.js +33 -0
  63. package/dist/server/managers/platform/database-manager.js +14 -0
  64. package/dist/server/managers/platform/event-bus-manager.js +7 -0
  65. package/dist/server/managers/platform/external-service-manager.js +11 -0
  66. package/dist/server/managers/platform/health-manager.js +7 -0
  67. package/dist/server/managers/platform/migration-manager.js +8 -0
  68. package/dist/server/managers/platform/search-index-manager.js +4 -0
  69. package/dist/server/managers/platform/secrets-manager.js +19 -0
  70. package/dist/server/managers/platform/session-manager.js +121 -0
  71. package/dist/server/managers/platform/storage-manager.js +16 -0
  72. package/dist/server/managers/platform/token-manager.js +37 -0
  73. package/dist/server/managers/platform/transaction-manager.js +8 -0
  74. package/dist/server/managers/platform/trusted-network.js +39 -0
  75. package/dist/server/managers/runtime.js +56 -0
  76. package/dist/server/managers/type-guards.js +4 -0
  77. package/dist/server/openapi.js +3512 -0
  78. package/dist/server/psyche-types.js +395 -0
  79. package/dist/server/repositories/activity-events.js +157 -0
  80. package/dist/server/repositories/collaboration.js +497 -0
  81. package/dist/server/repositories/comments.js +176 -0
  82. package/dist/server/repositories/deleted-entities.js +192 -0
  83. package/dist/server/repositories/domains.js +30 -0
  84. package/dist/server/repositories/event-log.js +64 -0
  85. package/dist/server/repositories/goals.js +159 -0
  86. package/dist/server/repositories/projects.js +214 -0
  87. package/dist/server/repositories/psyche.js +1356 -0
  88. package/dist/server/repositories/rewards.js +675 -0
  89. package/dist/server/repositories/settings.js +399 -0
  90. package/dist/server/repositories/tags.js +160 -0
  91. package/dist/server/repositories/task-runs.js +488 -0
  92. package/dist/server/repositories/tasks.js +413 -0
  93. package/dist/server/services/context.js +214 -0
  94. package/dist/server/services/dashboard.js +170 -0
  95. package/dist/server/services/entity-crud.js +576 -0
  96. package/dist/server/services/gamification.js +215 -0
  97. package/dist/server/services/insights.js +91 -0
  98. package/dist/server/services/projects.js +75 -0
  99. package/dist/server/services/psyche.js +63 -0
  100. package/dist/server/services/relations.js +28 -0
  101. package/dist/server/services/reviews.js +88 -0
  102. package/dist/server/services/run-recovery.js +13 -0
  103. package/dist/server/services/tagging.js +49 -0
  104. package/dist/server/services/task-run-watchdog.js +92 -0
  105. package/dist/server/services/work-time.js +176 -0
  106. package/dist/server/types.js +999 -0
  107. package/dist/server/web.js +91 -0
  108. package/openclaw.plugin.json +22 -10
  109. package/package.json +17 -4
  110. package/server/migrations/001_core.sql +333 -0
  111. package/server/migrations/002_psyche.sql +241 -0
  112. package/server/migrations/003_timer_execution.sql +18 -0
  113. package/server/migrations/004_psyche_linked_entities.sql +5 -0
  114. package/server/migrations/005_adaptive_schemas.sql +157 -0
  115. package/server/migrations/006_psyche_auth_setting.sql +4 -0
  116. package/server/migrations/007_deleted_entities.sql +16 -0
  117. package/skills/forge-openclaw/SKILL.md +189 -275
@@ -0,0 +1,4 @@
1
+ import { AbstractManager } from "../base.js";
2
+ export class SearchIndexManager extends AbstractManager {
3
+ name = "SearchIndexManager";
4
+ }
@@ -0,0 +1,19 @@
1
+ import { createHash, randomBytes, timingSafeEqual } from "node:crypto";
2
+ import { AbstractManager } from "../base.js";
3
+ export class SecretsManager extends AbstractManager {
4
+ name = "SecretsManager";
5
+ createSecret(prefix) {
6
+ return `${prefix}_${randomBytes(18).toString("hex")}`;
7
+ }
8
+ hashSecret(value) {
9
+ return createHash("sha256").update(value).digest("hex");
10
+ }
11
+ secureEquals(left, right) {
12
+ const leftBuffer = Buffer.from(left);
13
+ const rightBuffer = Buffer.from(right);
14
+ if (leftBuffer.length !== rightBuffer.length) {
15
+ return false;
16
+ }
17
+ return timingSafeEqual(leftBuffer, rightBuffer);
18
+ }
19
+ }
@@ -0,0 +1,121 @@
1
+ import { randomUUID } from "node:crypto";
2
+ import { AbstractAuditedManager } from "../base.js";
3
+ import { getSettings } from "../../repositories/settings.js";
4
+ import { isTrustedOperatorNetworkEntry } from "./trusted-network.js";
5
+ function cookieHeaderValue(name, value, maxAgeSeconds) {
6
+ return `${name}=${encodeURIComponent(value)}; Path=/; HttpOnly; SameSite=Strict; Max-Age=${maxAgeSeconds}`;
7
+ }
8
+ export class SessionManager extends AbstractAuditedManager {
9
+ databaseManager;
10
+ secretsManager;
11
+ configurationManager;
12
+ auditManager;
13
+ name = "SessionManager";
14
+ constructor(databaseManager, secretsManager, configurationManager, auditManager) {
15
+ super();
16
+ this.databaseManager = databaseManager;
17
+ this.secretsManager = secretsManager;
18
+ this.configurationManager = configurationManager;
19
+ this.auditManager = auditManager;
20
+ }
21
+ ensureLocalOperatorSession(headers, reply) {
22
+ const existing = this.readSessionFromHeaders(headers);
23
+ if (existing) {
24
+ return existing;
25
+ }
26
+ if (!this.isLocalOperatorRequest(headers)) {
27
+ throw new Error("Operator session bootstrap is only available on local loopback origins.");
28
+ }
29
+ const settings = getSettings();
30
+ const actorLabel = settings.profile.operatorName?.trim() || "Local Operator";
31
+ const issuedAt = new Date();
32
+ const expiresAt = new Date(issuedAt.getTime() + this.configurationManager.readRuntimeConfig().sessionTtlSeconds * 1000);
33
+ const sessionToken = this.secretsManager.createSecret("fg_session");
34
+ const sessionId = `ses_${randomUUID().replaceAll("-", "").slice(0, 10)}`;
35
+ this.databaseManager
36
+ .getConnection()
37
+ .prepare(`INSERT INTO operator_sessions (
38
+ id, session_hash, actor_label, issued_at, last_used_at, expires_at, revoked_at, created_at, updated_at
39
+ ) VALUES (?, ?, ?, ?, ?, ?, NULL, ?, ?)`)
40
+ .run(sessionId, this.secretsManager.hashSecret(sessionToken), actorLabel, issuedAt.toISOString(), issuedAt.toISOString(), expiresAt.toISOString(), issuedAt.toISOString(), issuedAt.toISOString());
41
+ reply.header("Set-Cookie", cookieHeaderValue(this.configurationManager.readRuntimeConfig().sessionCookieName, sessionToken, this.configurationManager.readRuntimeConfig().sessionTtlSeconds));
42
+ const session = {
43
+ id: sessionId,
44
+ actorLabel,
45
+ expiresAt: expiresAt.toISOString()
46
+ };
47
+ this.auditManager.record("operator.session_issued", "operator_session", sessionId, {
48
+ actor: actorLabel,
49
+ source: "ui",
50
+ origin: null,
51
+ host: null,
52
+ ip: null,
53
+ token: null,
54
+ session
55
+ }, {
56
+ actorLabel
57
+ });
58
+ return session;
59
+ }
60
+ revokeCurrentSession(headers, reply) {
61
+ const session = this.readSessionFromHeaders(headers);
62
+ if (!session) {
63
+ reply.header("Set-Cookie", cookieHeaderValue(this.configurationManager.readRuntimeConfig().sessionCookieName, "", 0));
64
+ return false;
65
+ }
66
+ this.databaseManager
67
+ .getConnection()
68
+ .prepare(`UPDATE operator_sessions SET revoked_at = ?, updated_at = ? WHERE id = ?`)
69
+ .run(new Date().toISOString(), new Date().toISOString(), session.id);
70
+ reply.header("Set-Cookie", cookieHeaderValue(this.configurationManager.readRuntimeConfig().sessionCookieName, "", 0));
71
+ return true;
72
+ }
73
+ readSessionFromHeaders(headers) {
74
+ const rawCookie = headers.cookie;
75
+ const cookieHeader = Array.isArray(rawCookie) ? rawCookie[0] : typeof rawCookie === "string" ? rawCookie : "";
76
+ if (!cookieHeader) {
77
+ return null;
78
+ }
79
+ const pairs = cookieHeader.split(";").map((entry) => entry.trim());
80
+ const needle = `${this.configurationManager.readRuntimeConfig().sessionCookieName}=`;
81
+ const sessionCookie = pairs.find((entry) => entry.startsWith(needle));
82
+ if (!sessionCookie) {
83
+ return null;
84
+ }
85
+ const sessionToken = decodeURIComponent(sessionCookie.slice(needle.length));
86
+ if (!sessionToken) {
87
+ return null;
88
+ }
89
+ const row = this.databaseManager
90
+ .getConnection()
91
+ .prepare(`SELECT id, actor_label, expires_at, revoked_at
92
+ FROM operator_sessions
93
+ WHERE session_hash = ?`)
94
+ .get(this.secretsManager.hashSecret(sessionToken));
95
+ if (!row || row.revoked_at) {
96
+ return null;
97
+ }
98
+ if (Date.parse(row.expires_at) <= Date.now()) {
99
+ this.databaseManager
100
+ .getConnection()
101
+ .prepare(`UPDATE operator_sessions SET revoked_at = ?, updated_at = ? WHERE id = ?`)
102
+ .run(new Date().toISOString(), new Date().toISOString(), row.id);
103
+ return null;
104
+ }
105
+ this.databaseManager
106
+ .getConnection()
107
+ .prepare(`UPDATE operator_sessions SET last_used_at = ?, updated_at = ? WHERE id = ?`)
108
+ .run(new Date().toISOString(), new Date().toISOString(), row.id);
109
+ return {
110
+ id: row.id,
111
+ actorLabel: row.actor_label,
112
+ expiresAt: row.expires_at
113
+ };
114
+ }
115
+ isLocalOperatorRequest(headers) {
116
+ const rawOrigin = Array.isArray(headers.origin) ? headers.origin[0] : headers.origin;
117
+ const rawHost = Array.isArray(headers.host) ? headers.host[0] : headers.host;
118
+ const candidates = [typeof rawOrigin === "string" ? rawOrigin : "", typeof rawHost === "string" ? rawHost : ""].filter(Boolean);
119
+ return candidates.some((entry) => isTrustedOperatorNetworkEntry(entry));
120
+ }
121
+ }
@@ -0,0 +1,16 @@
1
+ import path from "node:path";
2
+ import { AbstractManager } from "../base.js";
3
+ export class StorageManager extends AbstractManager {
4
+ cwd;
5
+ name = "StorageManager";
6
+ constructor(cwd = process.cwd()) {
7
+ super();
8
+ this.cwd = cwd;
9
+ }
10
+ resolveDataDir() {
11
+ return path.join(this.cwd, "data");
12
+ }
13
+ resolveClientDir() {
14
+ return path.join(this.cwd, "dist");
15
+ }
16
+ }
@@ -0,0 +1,37 @@
1
+ import { AbstractAuditedManager } from "../base.js";
2
+ import { createAgentToken, getAgentTokenById, revokeAgentToken, rotateAgentToken, verifyAgentToken } from "../../repositories/settings.js";
3
+ export class TokenManager extends AbstractAuditedManager {
4
+ auditManager;
5
+ name = "TokenManager";
6
+ constructor(auditManager) {
7
+ super();
8
+ this.auditManager = auditManager;
9
+ }
10
+ verifyBearerToken(token) {
11
+ return verifyAgentToken(token);
12
+ }
13
+ issueLocalAgentToken(input, context) {
14
+ const created = createAgentToken(input, { actor: context.actor, source: context.source });
15
+ this.auditManager.record("token.issued", "agent_token", created.tokenSummary.id, context, {
16
+ label: created.tokenSummary.label
17
+ });
18
+ return created;
19
+ }
20
+ rotateLocalAgentToken(tokenId, context) {
21
+ const rotated = rotateAgentToken(tokenId, { actor: context.actor, source: context.source });
22
+ if (rotated) {
23
+ this.auditManager.record("token.rotated", "agent_token", tokenId, context);
24
+ }
25
+ return rotated;
26
+ }
27
+ revokeLocalAgentToken(tokenId, context) {
28
+ const revoked = revokeAgentToken(tokenId, { actor: context.actor, source: context.source });
29
+ if (revoked) {
30
+ this.auditManager.record("token.revoked", "agent_token", tokenId, context);
31
+ }
32
+ return revoked;
33
+ }
34
+ getTokenById(tokenId) {
35
+ return getAgentTokenById(tokenId) ?? null;
36
+ }
37
+ }
@@ -0,0 +1,8 @@
1
+ import { AbstractManager } from "../base.js";
2
+ import { runInTransaction } from "../../db.js";
3
+ export class TransactionManager extends AbstractManager {
4
+ name = "TransactionManager";
5
+ run(operation) {
6
+ return runInTransaction(operation);
7
+ }
8
+ }
@@ -0,0 +1,39 @@
1
+ function readHostnameOrAddress(input) {
2
+ const trimmed = input.trim();
3
+ if (!trimmed) {
4
+ return null;
5
+ }
6
+ try {
7
+ return new URL(trimmed.includes("://") ? trimmed : `http://${trimmed}`).hostname.toLowerCase();
8
+ }
9
+ catch {
10
+ return trimmed
11
+ .replace(/^\[/, "")
12
+ .replace(/\]$/, "")
13
+ .split(":")[0]
14
+ .toLowerCase();
15
+ }
16
+ }
17
+ function isTailscaleIpv4(hostname) {
18
+ const match = hostname.match(/^(\d+)\.(\d+)\.(\d+)\.(\d+)$/);
19
+ if (!match) {
20
+ return false;
21
+ }
22
+ const octets = match.slice(1).map((value) => Number(value));
23
+ if (octets.some((value) => !Number.isInteger(value) || value < 0 || value > 255)) {
24
+ return false;
25
+ }
26
+ const [a, b] = octets;
27
+ return a === 100 && b >= 64 && b <= 127;
28
+ }
29
+ export function isTrustedOperatorNetworkEntry(input) {
30
+ const hostname = readHostnameOrAddress(input);
31
+ if (!hostname) {
32
+ return false;
33
+ }
34
+ return (hostname === "localhost" ||
35
+ hostname === "127.0.0.1" ||
36
+ hostname === "::1" ||
37
+ hostname.endsWith(".ts.net") ||
38
+ isTailscaleIpv4(hostname));
39
+ }
@@ -0,0 +1,56 @@
1
+ import { ConfigurationManager } from "./platform/configuration-manager.js";
2
+ import { SecretsManager } from "./platform/secrets-manager.js";
3
+ import { DatabaseManager } from "./platform/database-manager.js";
4
+ import { TransactionManager } from "./platform/transaction-manager.js";
5
+ import { MigrationManager } from "./platform/migration-manager.js";
6
+ import { StorageManager } from "./platform/storage-manager.js";
7
+ import { AuditManager } from "./platform/audit-manager.js";
8
+ import { SessionManager } from "./platform/session-manager.js";
9
+ import { TokenManager } from "./platform/token-manager.js";
10
+ import { AuthenticationManager } from "./platform/authentication-manager.js";
11
+ import { AuthorizationManager } from "./platform/authorization-manager.js";
12
+ import { EventBusManager } from "./platform/event-bus-manager.js";
13
+ import { HealthManager } from "./platform/health-manager.js";
14
+ import { BackgroundJobManager } from "./platform/background-job-manager.js";
15
+ import { ApiGatewayManager } from "./platform/api-gateway-manager.js";
16
+ import { ExternalServiceManager } from "./platform/external-service-manager.js";
17
+ import { SearchIndexManager } from "./platform/search-index-manager.js";
18
+ export function createManagerRuntime(options = {}) {
19
+ const configuration = new ConfigurationManager();
20
+ const database = new DatabaseManager();
21
+ database.configure(configuration.readRuntimeConfig({ dataRoot: options.dataRoot }).dataRoot);
22
+ const secrets = new SecretsManager();
23
+ const transaction = new TransactionManager();
24
+ const migration = new MigrationManager();
25
+ const storage = new StorageManager();
26
+ const audit = new AuditManager();
27
+ const session = new SessionManager(database, secrets, configuration, audit);
28
+ const token = new TokenManager(audit);
29
+ const authentication = new AuthenticationManager(session, token);
30
+ const authorization = new AuthorizationManager();
31
+ const eventBus = new EventBusManager();
32
+ const health = new HealthManager();
33
+ const backgroundJobs = new BackgroundJobManager();
34
+ const apiGateway = new ApiGatewayManager();
35
+ const externalServices = new ExternalServiceManager();
36
+ const searchIndex = new SearchIndexManager();
37
+ return {
38
+ configuration,
39
+ secrets,
40
+ database,
41
+ transaction,
42
+ migration,
43
+ storage,
44
+ authentication,
45
+ authorization,
46
+ session,
47
+ token,
48
+ eventBus,
49
+ audit,
50
+ health,
51
+ backgroundJobs,
52
+ apiGateway,
53
+ externalServices,
54
+ searchIndex
55
+ };
56
+ }
@@ -0,0 +1,4 @@
1
+ import { ManagerError } from "./contracts.js";
2
+ export function isManagerError(value) {
3
+ return value instanceof ManagerError;
4
+ }