@sireai/optimus 0.1.8 → 0.1.9

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 (66) hide show
  1. package/README.md +2 -1
  2. package/dist/cli/optimus.js +145 -81
  3. package/dist/cli/optimus.js.map +1 -1
  4. package/dist/config/load-config.js +3 -0
  5. package/dist/config/load-config.js.map +1 -1
  6. package/dist/integrations/feishu/feishu-auth-config.d.ts +7 -0
  7. package/dist/integrations/feishu/feishu-auth-config.js +37 -0
  8. package/dist/integrations/feishu/feishu-auth-config.js.map +1 -0
  9. package/dist/integrations/feishu/feishu-auth-service.d.ts +71 -0
  10. package/dist/integrations/feishu/feishu-auth-service.js +399 -0
  11. package/dist/integrations/feishu/feishu-auth-service.js.map +1 -0
  12. package/dist/integrations/feishu/feishu-auth-store.d.ts +29 -0
  13. package/dist/integrations/feishu/feishu-auth-store.js +113 -0
  14. package/dist/integrations/feishu/feishu-auth-store.js.map +1 -0
  15. package/dist/integrations/feishu/feishu-client.d.ts +52 -0
  16. package/dist/integrations/feishu/feishu-client.js +217 -0
  17. package/dist/integrations/feishu/feishu-client.js.map +1 -0
  18. package/dist/integrations/feishu/feishu-doc-service.d.ts +46 -0
  19. package/dist/integrations/feishu/feishu-doc-service.js +281 -0
  20. package/dist/integrations/feishu/feishu-doc-service.js.map +1 -0
  21. package/dist/integrations/feishu/feishu-token-store.d.ts +17 -0
  22. package/dist/integrations/feishu/feishu-token-store.js +34 -0
  23. package/dist/integrations/feishu/feishu-token-store.js.map +1 -0
  24. package/dist/integrations/feishu/feishu-user-service.d.ts +14 -0
  25. package/dist/integrations/feishu/feishu-user-service.js +60 -0
  26. package/dist/integrations/feishu/feishu-user-service.js.map +1 -0
  27. package/dist/integrations/jira/jira-cli.js +25 -11
  28. package/dist/integrations/jira/jira-cli.js.map +1 -1
  29. package/dist/integrations/jira/jira-client.d.ts +26 -0
  30. package/dist/integrations/jira/jira-client.js +111 -0
  31. package/dist/integrations/jira/jira-client.js.map +1 -1
  32. package/dist/integrations/jira/jira-submit.d.ts +5 -5
  33. package/dist/integrations/jira/jira-submit.js +97 -66
  34. package/dist/integrations/jira/jira-submit.js.map +1 -1
  35. package/dist/problem-solving-core/codex/codex-runner.d.ts +2 -0
  36. package/dist/problem-solving-core/codex/codex-runner.js +65 -0
  37. package/dist/problem-solving-core/codex/codex-runner.js.map +1 -1
  38. package/dist/task-environment/delivery/feishu-analysis-doc-service.d.ts +7 -25
  39. package/dist/task-environment/delivery/feishu-analysis-doc-service.js +32 -337
  40. package/dist/task-environment/delivery/feishu-analysis-doc-service.js.map +1 -1
  41. package/dist/task-environment/delivery/task-publication-service.d.ts +4 -0
  42. package/dist/task-environment/delivery/task-publication-service.js +56 -6
  43. package/dist/task-environment/delivery/task-publication-service.js.map +1 -1
  44. package/dist/task-environment/evidence/evidence-preparation-service.d.ts +36 -0
  45. package/dist/task-environment/evidence/evidence-preparation-service.js +341 -0
  46. package/dist/task-environment/evidence/evidence-preparation-service.js.map +1 -0
  47. package/dist/task-environment/intake/manual-problem-intake.js +15 -0
  48. package/dist/task-environment/intake/manual-problem-intake.js.map +1 -1
  49. package/dist/task-environment/observability/logger.js +21 -0
  50. package/dist/task-environment/observability/logger.js.map +1 -1
  51. package/dist/task-environment/orchestration/task-orchestrator.d.ts +3 -0
  52. package/dist/task-environment/orchestration/task-orchestrator.js +87 -1
  53. package/dist/task-environment/orchestration/task-orchestrator.js.map +1 -1
  54. package/dist/task-environment/orchestration/triage-runner.d.ts +2 -0
  55. package/dist/task-environment/orchestration/triage-runner.js +27 -1
  56. package/dist/task-environment/orchestration/triage-runner.js.map +1 -1
  57. package/dist/task-environment/runtime/optimus-runtime.js +4 -3
  58. package/dist/task-environment/runtime/optimus-runtime.js.map +1 -1
  59. package/dist/types.d.ts +3 -0
  60. package/embedded-skills/shared/video-keyframe-analyzer/SKILL.md +88 -0
  61. package/embedded-skills/shared/video-keyframe-analyzer/references/encountered-problems.md +12 -0
  62. package/embedded-skills/shared/video-keyframe-analyzer/references/triage-checklist.md +48 -0
  63. package/embedded-skills/shared/video-keyframe-analyzer/scripts/extract-keyframes.mjs +614 -0
  64. package/embedded-skills/shared/{repo-inspection → video-keyframe-analyzer}/skill.json +1 -1
  65. package/package.json +6 -2
  66. package/embedded-skills/shared/repo-inspection/SKILL.md +0 -9
@@ -0,0 +1,113 @@
1
+ import { chmodSync, existsSync, mkdirSync, readFileSync, writeFileSync } from "node:fs";
2
+ import { mkdir, readFile, rm, writeFile } from "node:fs/promises";
3
+ import { dirname, join } from "node:path";
4
+ import { resolveOptimusHomeDir } from "../../config/optimus-paths.js";
5
+ export function resolveDefaultFeishuAuthPath() {
6
+ return join(resolveOptimusHomeDir(), "auth", "feishu.json");
7
+ }
8
+ export class FileFeishuAuthStore {
9
+ filePath;
10
+ constructor(filePath = resolveDefaultFeishuAuthPath()) {
11
+ this.filePath = filePath;
12
+ }
13
+ async read() {
14
+ try {
15
+ return normalizeAuthRecord(JSON.parse(await readFile(this.filePath, "utf8")));
16
+ }
17
+ catch {
18
+ return undefined;
19
+ }
20
+ }
21
+ readSync() {
22
+ return readFeishuAuthRecordSync(this.filePath);
23
+ }
24
+ async write(record) {
25
+ await mkdir(dirname(this.filePath), { recursive: true });
26
+ await writeFile(this.filePath, `${JSON.stringify(record, null, 2)}\n`, "utf8");
27
+ try {
28
+ chmodSync(this.filePath, 0o600);
29
+ }
30
+ catch {
31
+ // chmod is best-effort.
32
+ }
33
+ }
34
+ async clear() {
35
+ await rm(this.filePath, { force: true });
36
+ }
37
+ }
38
+ export function readFeishuAuthRecordSync(filePath = resolveDefaultFeishuAuthPath()) {
39
+ if (!existsSync(filePath)) {
40
+ return undefined;
41
+ }
42
+ try {
43
+ return normalizeAuthRecord(JSON.parse(readFileSync(filePath, "utf8")));
44
+ }
45
+ catch {
46
+ return undefined;
47
+ }
48
+ }
49
+ export function writeFeishuAuthRecordSync(record, filePath = resolveDefaultFeishuAuthPath()) {
50
+ mkdirSync(dirname(filePath), { recursive: true });
51
+ writeFileSync(filePath, `${JSON.stringify(record, null, 2)}\n`, "utf8");
52
+ try {
53
+ chmodSync(filePath, 0o600);
54
+ }
55
+ catch {
56
+ // chmod is best-effort.
57
+ }
58
+ }
59
+ export function isFeishuAccessTokenExpired(record, nowMs = Date.now()) {
60
+ return nowMs >= record.expiresAtMs - 60_000;
61
+ }
62
+ export function isFeishuRefreshTokenExpired(record, nowMs = Date.now()) {
63
+ return nowMs >= record.refreshExpiresAtMs - 60_000;
64
+ }
65
+ function normalizeAuthRecord(value) {
66
+ if (!value || typeof value !== "object" || Array.isArray(value)) {
67
+ return undefined;
68
+ }
69
+ const record = value;
70
+ const accessToken = readString(record, ["accessToken", "access_token"]);
71
+ const refreshToken = readString(record, ["refreshToken", "refresh_token"]);
72
+ const expiresAtMs = readTimestampMs(record, ["expiresAtMs", "expires_at"], "seconds");
73
+ const refreshExpiresAtMs = readTimestampMs(record, ["refreshExpiresAtMs", "refresh_expires_at"], "seconds");
74
+ if (!accessToken || !refreshToken || !Number.isFinite(expiresAtMs) || !Number.isFinite(refreshExpiresAtMs)) {
75
+ return undefined;
76
+ }
77
+ const openId = readString(record, ["openId", "open_id"]);
78
+ const tenantKey = readString(record, ["tenantKey", "tenant_key"]);
79
+ const userId = readString(record, ["userId", "user_id"]);
80
+ const baseUrl = readString(record, ["baseUrl", "base_url"]);
81
+ return {
82
+ accessToken,
83
+ refreshToken,
84
+ expiresAtMs,
85
+ refreshExpiresAtMs,
86
+ ...(openId ? { openId } : {}),
87
+ ...(tenantKey ? { tenantKey } : {}),
88
+ ...(userId ? { userId } : {}),
89
+ ...(baseUrl ? { baseUrl } : {})
90
+ };
91
+ }
92
+ function readString(record, keys) {
93
+ for (const key of keys) {
94
+ const raw = record[key];
95
+ if (typeof raw === "string" && raw.trim()) {
96
+ return raw.trim();
97
+ }
98
+ }
99
+ return undefined;
100
+ }
101
+ function readTimestampMs(record, keys, snakeCaseUnit) {
102
+ for (const key of keys) {
103
+ const raw = record[key];
104
+ const parsed = typeof raw === "number" ? raw : typeof raw === "string" ? Number(raw) : Number.NaN;
105
+ if (!Number.isFinite(parsed)) {
106
+ continue;
107
+ }
108
+ const shouldTreatAsSeconds = key.includes("_") && snakeCaseUnit === "seconds";
109
+ return shouldTreatAsSeconds ? parsed * 1000 : parsed;
110
+ }
111
+ return Number.NaN;
112
+ }
113
+ //# sourceMappingURL=feishu-auth-store.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"feishu-auth-store.js","sourceRoot":"","sources":["../../../src/integrations/feishu/feishu-auth-store.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,52 @@
1
+ import type { OptimusConfig } from "../../types.js";
2
+ import { FeishuAuthService, type FeishuAuthServiceOptions } from "./feishu-auth-service.js";
3
+ import { type FeishuTokenStore } from "./feishu-token-store.js";
4
+ export declare class FeishuIntegrationError extends Error {
5
+ readonly diagnostics: {
6
+ category: "config_missing" | "auth_failed" | "request_failed";
7
+ status?: number;
8
+ code?: number;
9
+ detail?: string;
10
+ };
11
+ constructor(message: string, diagnostics: {
12
+ category: "config_missing" | "auth_failed" | "request_failed";
13
+ status?: number;
14
+ code?: number;
15
+ detail?: string;
16
+ });
17
+ }
18
+ export interface FeishuClientOptions {
19
+ config?: Pick<OptimusConfig, "delivery">;
20
+ env?: NodeJS.ProcessEnv;
21
+ fetchImpl?: typeof globalThis.fetch;
22
+ tokenStore?: FeishuTokenStore;
23
+ authService?: Pick<FeishuAuthService, "getValidAccessToken" | "recoverExpiredAuth" | "readStatus">;
24
+ authServiceOptions?: Omit<FeishuAuthServiceOptions, "env" | "fetchImpl">;
25
+ }
26
+ export declare class FeishuClient {
27
+ private readonly env;
28
+ private readonly fetchImpl;
29
+ private readonly tokenStore;
30
+ private readonly authService;
31
+ private readonly baseUrl;
32
+ private readonly appId;
33
+ private readonly appSecret;
34
+ constructor(options?: FeishuClientOptions);
35
+ isConfigured(): boolean;
36
+ get<T>(path: string, query?: Record<string, string | undefined>): Promise<T>;
37
+ post<T>(path: string, body?: unknown, query?: Record<string, string | undefined>): Promise<T>;
38
+ patch<T>(path: string, body?: unknown, query?: Record<string, string | undefined>): Promise<T>;
39
+ private request;
40
+ private getTenantAccessToken;
41
+ private getAccessToken;
42
+ private buildUrl;
43
+ private readResponsePayload;
44
+ private payloadHasError;
45
+ private extractCode;
46
+ private isAuthExpired;
47
+ private readString;
48
+ private readNumber;
49
+ private readConfiguredValue;
50
+ private normalizeBaseUrl;
51
+ private compact;
52
+ }
@@ -0,0 +1,217 @@
1
+ import { FeishuAuthService } from "./feishu-auth-service.js";
2
+ import { FileFeishuTokenStore } from "./feishu-token-store.js";
3
+ const DEFAULT_FEISHU_BASE_URL = "https://open.feishu.cn";
4
+ const TENANT_TOKEN_SKEW_MS = 5 * 60 * 1000;
5
+ export class FeishuIntegrationError extends Error {
6
+ diagnostics;
7
+ constructor(message, diagnostics) {
8
+ super(message);
9
+ this.diagnostics = diagnostics;
10
+ this.name = "FeishuIntegrationError";
11
+ }
12
+ }
13
+ export class FeishuClient {
14
+ env;
15
+ fetchImpl;
16
+ tokenStore;
17
+ authService;
18
+ baseUrl;
19
+ appId;
20
+ appSecret;
21
+ constructor(options = {}) {
22
+ this.env = options.env ?? process.env;
23
+ this.fetchImpl = options.fetchImpl ?? globalThis.fetch?.bind(globalThis);
24
+ this.tokenStore = options.tokenStore ?? new FileFeishuTokenStore();
25
+ this.authService = options.authService ?? new FeishuAuthService({
26
+ env: this.env,
27
+ fetchImpl: this.fetchImpl,
28
+ ...(options.authServiceOptions ?? {})
29
+ });
30
+ const feishuConfig = options.config?.delivery.feishu;
31
+ this.baseUrl = this.normalizeBaseUrl(feishuConfig?.baseUrl ?? this.env.FEISHU_BASE_URL ?? DEFAULT_FEISHU_BASE_URL);
32
+ this.appId = this.readConfiguredValue(feishuConfig?.appId, this.env.FEISHU_APP_ID);
33
+ this.appSecret = this.readConfiguredValue(feishuConfig?.appSecret, this.env.FEISHU_APP_SECRET);
34
+ }
35
+ isConfigured() {
36
+ return this.authService.readStatus().authenticated || Boolean(this.appId && this.appSecret);
37
+ }
38
+ async get(path, query) {
39
+ return await this.request("GET", path, undefined, query);
40
+ }
41
+ async post(path, body, query) {
42
+ return await this.request("POST", path, body, query);
43
+ }
44
+ async patch(path, body, query) {
45
+ return await this.request("PATCH", path, body, query);
46
+ }
47
+ async request(method, path, body, query, retryAfterAuthRefresh = true) {
48
+ const token = await this.getAccessToken();
49
+ const response = await this.fetchImpl(this.buildUrl(path, query), {
50
+ method,
51
+ headers: {
52
+ authorization: `Bearer ${token}`,
53
+ "content-type": "application/json; charset=utf-8"
54
+ },
55
+ ...(body === undefined ? {} : { body: JSON.stringify(body) })
56
+ });
57
+ const payload = await this.readResponsePayload(response);
58
+ if (response.ok && !this.payloadHasError(payload)) {
59
+ return payload;
60
+ }
61
+ const code = this.extractCode(payload);
62
+ if (retryAfterAuthRefresh && this.isAuthExpired(response.status, code, payload)) {
63
+ await this.tokenStore.clearTenantToken().catch(() => undefined);
64
+ await this.authService.recoverExpiredAuth?.("request_auth_expired").catch(() => undefined);
65
+ return await this.request(method, path, body, query, false);
66
+ }
67
+ throw new FeishuIntegrationError("Feishu API request failed.", {
68
+ category: response.status === 401 || response.status === 403 ? "auth_failed" : "request_failed",
69
+ status: response.status,
70
+ ...(code !== undefined ? { code } : {}),
71
+ detail: this.compact(JSON.stringify(payload))
72
+ });
73
+ }
74
+ async getTenantAccessToken() {
75
+ if (!this.fetchImpl) {
76
+ throw new FeishuIntegrationError("Feishu integration requires global fetch.", { category: "request_failed" });
77
+ }
78
+ if (!this.appId || !this.appSecret) {
79
+ throw new FeishuIntegrationError("Feishu auth is not ready. Run `optimus feishu auth login`.", {
80
+ category: "config_missing"
81
+ });
82
+ }
83
+ const cached = await this.tokenStore.readTenantToken();
84
+ if (cached?.tenantAccessToken && cached.expireAtMs > Date.now() + TENANT_TOKEN_SKEW_MS) {
85
+ return cached.tenantAccessToken;
86
+ }
87
+ const response = await this.fetchImpl(`${this.baseUrl}/open-apis/auth/v3/tenant_access_token/internal`, {
88
+ method: "POST",
89
+ headers: {
90
+ "content-type": "application/json; charset=utf-8"
91
+ },
92
+ body: JSON.stringify({
93
+ app_id: this.appId,
94
+ app_secret: this.appSecret
95
+ })
96
+ });
97
+ const payload = await this.readResponsePayload(response);
98
+ const token = this.readString(payload, ["tenant_access_token", "tenantAccessToken"]);
99
+ const expireSeconds = this.readNumber(payload, ["expire"]);
100
+ if (!response.ok || this.payloadHasError(payload) || !token) {
101
+ const code = this.extractCode(payload);
102
+ throw new FeishuIntegrationError("Feishu tenant token request failed.", {
103
+ category: "auth_failed",
104
+ status: response.status,
105
+ ...(code !== undefined ? { code } : {}),
106
+ detail: this.compact(JSON.stringify(payload))
107
+ });
108
+ }
109
+ await this.tokenStore.writeTenantToken({
110
+ tenantAccessToken: token,
111
+ expireAtMs: Date.now() + Math.max(60, expireSeconds ?? 7200) * 1000
112
+ }).catch(() => undefined);
113
+ return token;
114
+ }
115
+ async getAccessToken() {
116
+ try {
117
+ const authenticated = await this.authService.getValidAccessToken();
118
+ return authenticated.accessToken;
119
+ }
120
+ catch (error) {
121
+ if (this.appId && this.appSecret) {
122
+ return await this.getTenantAccessToken();
123
+ }
124
+ if (error instanceof Error) {
125
+ throw new FeishuIntegrationError(error.message, {
126
+ category: /expired|failed/i.test(error.message) ? "auth_failed" : "config_missing"
127
+ });
128
+ }
129
+ throw error;
130
+ }
131
+ }
132
+ buildUrl(path, query) {
133
+ const normalizedPath = path.startsWith("/") ? path : `/${path}`;
134
+ const url = new URL(`${this.baseUrl}${normalizedPath}`);
135
+ for (const [key, value] of Object.entries(query ?? {})) {
136
+ if (value?.trim()) {
137
+ url.searchParams.set(key, value.trim());
138
+ }
139
+ }
140
+ return url.toString();
141
+ }
142
+ async readResponsePayload(response) {
143
+ const text = await response.text();
144
+ if (!text.trim()) {
145
+ return {};
146
+ }
147
+ try {
148
+ return JSON.parse(text);
149
+ }
150
+ catch {
151
+ return { raw: text };
152
+ }
153
+ }
154
+ payloadHasError(payload) {
155
+ const code = this.extractCode(payload);
156
+ return code !== undefined && code !== 0;
157
+ }
158
+ extractCode(payload) {
159
+ if (!payload || typeof payload !== "object" || Array.isArray(payload)) {
160
+ return undefined;
161
+ }
162
+ const record = payload;
163
+ const raw = record.code ?? record.Code;
164
+ return typeof raw === "number" ? raw : typeof raw === "string" && raw.trim() ? Number(raw) : undefined;
165
+ }
166
+ isAuthExpired(status, code, payload) {
167
+ if (status === 401) {
168
+ return true;
169
+ }
170
+ const detail = JSON.stringify(payload).toLowerCase();
171
+ return [
172
+ 99991663,
173
+ 99991664,
174
+ 99991668,
175
+ 99991672,
176
+ 99991673
177
+ ].includes(code ?? -1) || /token|auth|unauthorized|expired/.test(detail);
178
+ }
179
+ readString(value, keys) {
180
+ if (!value || typeof value !== "object" || Array.isArray(value)) {
181
+ return undefined;
182
+ }
183
+ const record = value;
184
+ for (const key of keys) {
185
+ const raw = record[key];
186
+ if (typeof raw === "string" && raw.trim()) {
187
+ return raw.trim();
188
+ }
189
+ }
190
+ return undefined;
191
+ }
192
+ readNumber(value, keys) {
193
+ if (!value || typeof value !== "object" || Array.isArray(value)) {
194
+ return undefined;
195
+ }
196
+ const record = value;
197
+ for (const key of keys) {
198
+ const raw = record[key];
199
+ const parsed = typeof raw === "number" ? raw : typeof raw === "string" ? Number(raw) : Number.NaN;
200
+ if (Number.isFinite(parsed)) {
201
+ return parsed;
202
+ }
203
+ }
204
+ return undefined;
205
+ }
206
+ readConfiguredValue(configValue, envValue) {
207
+ const value = configValue?.trim() || envValue?.trim();
208
+ return value || undefined;
209
+ }
210
+ normalizeBaseUrl(value) {
211
+ return value.trim().replace(/\/+$/u, "");
212
+ }
213
+ compact(value) {
214
+ return value.replace(/\s+/gu, " ").trim().slice(0, 2000);
215
+ }
216
+ }
217
+ //# sourceMappingURL=feishu-client.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"feishu-client.js","sourceRoot":"","sources":["../../../src/integrations/feishu/feishu-client.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,46 @@
1
+ import type { OptimusConfig } from "../../types.js";
2
+ import { FeishuClient, type FeishuClientOptions } from "./feishu-client.js";
3
+ export interface FeishuWikiNodeRef {
4
+ nodeToken: string;
5
+ title: string;
6
+ spaceId?: string;
7
+ url?: string;
8
+ }
9
+ export interface FeishuCreatedDocument {
10
+ token: string;
11
+ url: string;
12
+ nodeToken?: string;
13
+ spaceId?: string;
14
+ }
15
+ export interface FeishuDocumentServiceOptions {
16
+ client?: Pick<FeishuClient, "get" | "post" | "patch" | "isConfigured">;
17
+ config?: Pick<OptimusConfig, "delivery">;
18
+ authServiceOptions?: FeishuClientOptions["authServiceOptions"];
19
+ }
20
+ export declare class FeishuDocumentService {
21
+ private readonly client;
22
+ constructor(options?: FeishuDocumentServiceOptions);
23
+ isConfigured(): boolean;
24
+ getWikiNode(nodeToken: string): Promise<FeishuWikiNodeRef | undefined>;
25
+ listWikiNodes(spaceId: string): Promise<FeishuWikiNodeRef[]>;
26
+ createMarkdownDocument(input: {
27
+ title: string;
28
+ markdownPath: string;
29
+ parentNodeToken?: string;
30
+ }): Promise<FeishuCreatedDocument>;
31
+ createEmptyDocument(title: string): Promise<FeishuCreatedDocument>;
32
+ private createDocument;
33
+ private appendMarkdown;
34
+ private convertMarkdown;
35
+ private updateTitleBestEffort;
36
+ private toBasicBlocks;
37
+ private toTextBlock;
38
+ private extractDocumentToken;
39
+ private extractDocumentUrl;
40
+ private extractWikiNodes;
41
+ private extractWikiNode;
42
+ private extractWikiNodeToken;
43
+ private extractWikiSpaceId;
44
+ private findArray;
45
+ private readString;
46
+ }