coaiajs 0.3.0 → 0.3.2
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.
- package/KINSHIP.md +1 -1
- package/README.md +191 -75
- package/dist/mcp/config.d.ts.map +1 -0
- package/dist/mcp/config.js +0 -2
- package/dist/mcp/config.js.map +1 -0
- package/dist/mcp/prompts.d.ts.map +1 -0
- package/dist/mcp/prompts.js.map +1 -0
- package/dist/mcp/resources.d.ts.map +1 -0
- package/dist/mcp/resources.js.map +1 -0
- package/dist/mcp/server.d.ts.map +1 -0
- package/dist/mcp/server.js +1 -1
- package/dist/mcp/server.js.map +1 -0
- package/dist/mcp/tools/coaiapy-tools.d.ts.map +1 -0
- package/dist/mcp/tools/coaiapy-tools.js.map +1 -0
- package/dist/mcp/tools/index.d.ts.map +1 -0
- package/dist/mcp/tools/index.js.map +1 -0
- package/dist/src/audio.d.ts.map +1 -0
- package/dist/src/audio.js.map +1 -0
- package/dist/src/cli-helpers.d.ts.map +1 -0
- package/dist/src/cli-helpers.js.map +1 -0
- package/dist/src/cli.d.ts.map +1 -0
- package/dist/src/cli.js +1 -0
- package/dist/src/cli.js.map +1 -0
- package/dist/src/config.d.ts.map +1 -0
- package/dist/src/config.js.map +1 -0
- package/dist/src/environment.d.ts.map +1 -0
- package/dist/src/environment.js.map +1 -0
- package/dist/src/github.d.ts.map +1 -0
- package/dist/src/github.js.map +1 -0
- package/dist/src/index.d.ts +1 -0
- package/dist/src/index.d.ts.map +1 -0
- package/dist/src/index.js +1 -0
- package/dist/src/index.js.map +1 -0
- package/dist/src/langfuse/client.d.ts.map +1 -0
- package/dist/src/langfuse/client.js.map +1 -0
- package/dist/src/langfuse/comments.d.ts.map +1 -0
- package/dist/src/langfuse/comments.js.map +1 -0
- package/dist/src/langfuse/datasets.d.ts.map +1 -0
- package/dist/src/langfuse/datasets.js.map +1 -0
- package/dist/src/langfuse/index.d.ts +1 -0
- package/dist/src/langfuse/index.d.ts.map +1 -0
- package/dist/src/langfuse/index.js.map +1 -0
- package/dist/src/langfuse/media.d.ts.map +1 -0
- package/dist/src/langfuse/media.js.map +1 -0
- package/dist/src/langfuse/observations.d.ts.map +1 -0
- package/dist/src/langfuse/observations.js.map +1 -0
- package/dist/src/langfuse/prompts.d.ts +5 -1
- package/dist/src/langfuse/prompts.d.ts.map +1 -0
- package/dist/src/langfuse/prompts.js +16 -3
- package/dist/src/langfuse/prompts.js.map +1 -0
- package/dist/src/langfuse/scores.d.ts.map +1 -0
- package/dist/src/langfuse/scores.js.map +1 -0
- package/dist/src/langfuse/traces.d.ts.map +1 -0
- package/dist/src/langfuse/traces.js.map +1 -0
- package/dist/src/llm.d.ts.map +1 -0
- package/dist/src/llm.js.map +1 -0
- package/dist/src/narrative/graph-manager.d.ts.map +1 -0
- package/dist/src/narrative/graph-manager.js.map +1 -0
- package/dist/src/narrative/index.d.ts.map +1 -0
- package/dist/src/narrative/index.js.map +1 -0
- package/dist/src/narrative/markdown-export.d.ts.map +1 -0
- package/dist/src/narrative/markdown-export.js.map +1 -0
- package/dist/src/narrative/tool-definitions.d.ts.map +1 -0
- package/dist/src/narrative/tool-definitions.js.map +1 -0
- package/dist/src/narrative/tool-handlers.d.ts.map +1 -0
- package/dist/src/narrative/tool-handlers.js.map +1 -0
- package/dist/src/narrative/types.d.ts.map +1 -0
- package/dist/src/narrative/types.js.map +1 -0
- package/dist/src/narrative/validation.d.ts.map +1 -0
- package/dist/src/narrative/validation.js.map +1 -0
- package/dist/src/pde/index.d.ts.map +1 -0
- package/dist/src/pde/index.js.map +1 -0
- package/dist/src/pde/mcp-handlers.d.ts.map +1 -0
- package/dist/src/pde/mcp-handlers.js.map +1 -0
- package/dist/src/pde/mcp-tools.d.ts.map +1 -0
- package/dist/src/pde/mcp-tools.js.map +1 -0
- package/dist/src/pde/session-manager.d.ts.map +1 -0
- package/dist/src/pde/session-manager.js.map +1 -0
- package/dist/src/pde/stc-mapper.d.ts.map +1 -0
- package/dist/src/pde/stc-mapper.js.map +1 -0
- package/dist/src/pipeline/index.d.ts.map +1 -0
- package/dist/src/pipeline/index.js.map +1 -0
- package/dist/src/pipeline/template-engine.d.ts.map +1 -0
- package/dist/src/pipeline/template-engine.js.map +1 -0
- package/dist/src/planning/index.d.ts.map +1 -0
- package/dist/src/planning/index.js.map +1 -0
- package/dist/src/planning/mcp-handlers.d.ts.map +1 -0
- package/dist/src/planning/mcp-handlers.js.map +1 -0
- package/dist/src/planning/mcp-tools.d.ts.map +1 -0
- package/dist/src/planning/mcp-tools.js.map +1 -0
- package/dist/src/planning/plan-parser.d.ts.map +1 -0
- package/dist/src/planning/plan-parser.js.map +1 -0
- package/dist/src/redis.d.ts.map +1 -0
- package/dist/src/redis.js.map +1 -0
- package/dist/src/types.d.ts.map +1 -0
- package/dist/src/types.js.map +1 -0
- package/dist/src/version.d.ts.map +1 -0
- package/dist/src/version.js.map +1 -0
- package/llms-full.txt +361 -0
- package/llms.txt +43 -0
- package/package.json +79 -12
- package/.claude/settings.local.json +0 -17
- package/.claude-plugin/marketplace.json +0 -26
- package/articles/academic/NOTES.md +0 -1
- package/articles/academic/README.md +0 -1
- package/articles/academic/creative-orientation-vs-problem-solving.md +0 -177
- package/articles/academic/jsonl-knowledge-graphs-agent-memory.md +0 -142
- package/articles/academic/langfuse-observability-llm-pipelines.md +0 -144
- package/articles/academic/medicine-wheel-software-architecture.md +0 -163
- package/articles/academic/mmot-autonomous-agents.md +0 -156
- package/articles/academic/model-context-protocol-interagent.md +0 -161
- package/articles/academic/pde-prompt-decomposition.md +0 -186
- package/articles/academic/structural-tension-in-ai-agents.md +0 -134
- package/articles/reviews/mcp-protocol-design-review.md +0 -170
- package/articles/reviews/observability-ai-systems-review.md +0 -176
- package/articles/reviews/prompt-engineering-decomposition-review.md +0 -184
- package/articles/surveys/agent-orchestration-survey.md +0 -186
- package/articles/surveys/knowledge-graph-storage-survey.md +0 -204
- package/articles/surveys/structural-tension-methodology-survey.md +0 -154
- package/articles/technical/aws-sdk-v3-polly.md +0 -270
- package/articles/technical/commander-cli-framework.md +0 -262
- package/articles/technical/dotenv-config-patterns.md +0 -360
- package/articles/technical/ioredis-vs-redis.md +0 -142
- package/articles/technical/langfuse-js-sdk-vs-rest.md +0 -191
- package/articles/technical/mcp-sdk-typescript.md +0 -291
- package/articles/technical/octokit-github-api.md +0 -293
- package/articles/technical/openai-sdk-modern.md +0 -231
- package/articles/technical/yaml-parsing-node.md +0 -266
- package/articles/technical/zod-runtime-validation.md +0 -212
- package/coaiajs-langfuse-claude-plugin/.claude-plugin/marketplace.json +0 -16
- package/coaiajs-langfuse-claude-plugin/.claude-plugin/plugin.json +0 -10
- package/coaiajs-langfuse-claude-plugin/.mcp.json +0 -8
- package/coaiajs-langfuse-claude-plugin/README.md +0 -60
- package/mcp/config.ts +0 -225
- package/mcp/prompts.ts +0 -131
- package/mcp/resources.ts +0 -84
- package/mcp/server.ts +0 -519
- package/mcp/tools/coaiapy-tools.ts +0 -366
- package/mcp/tools/index.ts +0 -4
- package/src/audio.ts +0 -76
- package/src/cli-helpers.ts +0 -86
- package/src/cli.ts +0 -1261
- package/src/config.ts +0 -207
- package/src/environment.ts +0 -171
- package/src/github.ts +0 -143
- package/src/index.ts +0 -82
- package/src/langfuse/client.ts +0 -105
- package/src/langfuse/comments.ts +0 -52
- package/src/langfuse/datasets.ts +0 -178
- package/src/langfuse/index.ts +0 -37
- package/src/langfuse/media.ts +0 -193
- package/src/langfuse/observations.ts +0 -155
- package/src/langfuse/prompts.ts +0 -157
- package/src/langfuse/scores.ts +0 -456
- package/src/langfuse/traces.ts +0 -353
- package/src/llm.ts +0 -106
- package/src/narrative/graph-manager.ts +0 -1358
- package/src/narrative/index.ts +0 -188
- package/src/narrative/markdown-export.ts +0 -535
- package/src/narrative/tool-definitions.ts +0 -635
- package/src/narrative/tool-handlers.ts +0 -528
- package/src/narrative/types.ts +0 -9
- package/src/narrative/validation.ts +0 -179
- package/src/pde/index.ts +0 -34
- package/src/pde/mcp-handlers.ts +0 -359
- package/src/pde/mcp-tools.ts +0 -201
- package/src/pde/session-manager.ts +0 -248
- package/src/pde/stc-mapper.ts +0 -298
- package/src/pipeline/index.ts +0 -7
- package/src/pipeline/template-engine.ts +0 -398
- package/src/planning/index.ts +0 -32
- package/src/planning/mcp-handlers.ts +0 -369
- package/src/planning/mcp-tools.ts +0 -155
- package/src/planning/plan-parser.ts +0 -587
- package/src/redis.ts +0 -111
- package/src/types.ts +0 -281
- package/src/version.ts +0 -39
- package/test/config.test.mjs +0 -93
- package/tsconfig.json +0 -26
package/src/config.ts
DELETED
|
@@ -1,207 +0,0 @@
|
|
|
1
|
-
// coaiajs/src/config.ts — Config management
|
|
2
|
-
// Priority: env vars > .env > coaia.json > defaults
|
|
3
|
-
|
|
4
|
-
import { readFileSync, existsSync } from 'node:fs';
|
|
5
|
-
import { resolve, join, isAbsolute } from 'node:path';
|
|
6
|
-
import { homedir } from 'node:os';
|
|
7
|
-
import dotenv from 'dotenv';
|
|
8
|
-
import type { CoaiaConfig } from './types.js';
|
|
9
|
-
|
|
10
|
-
const CONFIG_FILENAMES = [
|
|
11
|
-
'coaia.json',
|
|
12
|
-
'.coaia/config.json',
|
|
13
|
-
'.config/jgwill/coaia.json',
|
|
14
|
-
'Documents/coaia.json',
|
|
15
|
-
];
|
|
16
|
-
|
|
17
|
-
function expandPath(filePath: string): string {
|
|
18
|
-
if (filePath === '~') return homedir();
|
|
19
|
-
if (filePath.startsWith('~/')) return join(homedir(), filePath.slice(2));
|
|
20
|
-
return isAbsolute(filePath) ? filePath : resolve(process.cwd(), filePath);
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
/** Search for an existing coaia.json config file. */
|
|
24
|
-
export function findExistingConfig(): string | null {
|
|
25
|
-
const searchDirs = [process.cwd(), homedir()];
|
|
26
|
-
|
|
27
|
-
for (const dir of searchDirs) {
|
|
28
|
-
for (const filename of CONFIG_FILENAMES) {
|
|
29
|
-
const candidate = join(dir, filename);
|
|
30
|
-
if (existsSync(candidate)) {
|
|
31
|
-
return candidate;
|
|
32
|
-
}
|
|
33
|
-
}
|
|
34
|
-
}
|
|
35
|
-
return null;
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
/** Resolve dotenv files in priority order. Earlier files win over later files. */
|
|
39
|
-
export function findEnvFiles(envPath?: string): string[] {
|
|
40
|
-
const explicitEnvPath =
|
|
41
|
-
envPath ?? process.env['COAIAJS_ENV_PATH'] ?? process.env['COAIAPY_ENV_PATH'];
|
|
42
|
-
|
|
43
|
-
if (explicitEnvPath) {
|
|
44
|
-
return [expandPath(explicitEnvPath)].filter((candidate) => existsSync(candidate));
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
return [
|
|
48
|
-
resolve(process.cwd(), '.env'),
|
|
49
|
-
join(homedir(), '.coaia', '.env'),
|
|
50
|
-
].filter((candidate) => existsSync(candidate));
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
/** Deep-merge two config objects; override wins on conflicts. */
|
|
54
|
-
export function mergeConfigs(
|
|
55
|
-
base: Partial<CoaiaConfig>,
|
|
56
|
-
override: Partial<CoaiaConfig>,
|
|
57
|
-
): CoaiaConfig {
|
|
58
|
-
const result: Record<string, unknown> = { ...base };
|
|
59
|
-
|
|
60
|
-
for (const [key, val] of Object.entries(override)) {
|
|
61
|
-
if (
|
|
62
|
-
val !== null &&
|
|
63
|
-
val !== undefined &&
|
|
64
|
-
typeof val === 'object' &&
|
|
65
|
-
!Array.isArray(val) &&
|
|
66
|
-
typeof result[key] === 'object' &&
|
|
67
|
-
result[key] !== null &&
|
|
68
|
-
!Array.isArray(result[key])
|
|
69
|
-
) {
|
|
70
|
-
result[key] = mergeConfigs(
|
|
71
|
-
result[key] as Partial<CoaiaConfig>,
|
|
72
|
-
val as Partial<CoaiaConfig>,
|
|
73
|
-
);
|
|
74
|
-
} else if (val !== undefined) {
|
|
75
|
-
result[key] = val;
|
|
76
|
-
}
|
|
77
|
-
}
|
|
78
|
-
return result as CoaiaConfig;
|
|
79
|
-
}
|
|
80
|
-
|
|
81
|
-
function loadJsonConfig(filePath: string): Partial<CoaiaConfig> {
|
|
82
|
-
try {
|
|
83
|
-
const raw = readFileSync(filePath, 'utf-8');
|
|
84
|
-
return JSON.parse(raw) as Partial<CoaiaConfig>;
|
|
85
|
-
} catch {
|
|
86
|
-
return {};
|
|
87
|
-
}
|
|
88
|
-
}
|
|
89
|
-
|
|
90
|
-
function parseBool(value: string | undefined): boolean | undefined {
|
|
91
|
-
if (!value) return undefined;
|
|
92
|
-
return ['1', 'true', 'yes', 'on'].includes(value.toLowerCase());
|
|
93
|
-
}
|
|
94
|
-
|
|
95
|
-
function envOverrides(): Partial<CoaiaConfig> {
|
|
96
|
-
const cfg: Partial<CoaiaConfig> = {};
|
|
97
|
-
const env = process.env;
|
|
98
|
-
|
|
99
|
-
// Redis
|
|
100
|
-
const upstashUrl = env['UPSTASH_REDIS_REST_URL'] ?? env['KV_REST_API_URL'];
|
|
101
|
-
const upstashToken = env['UPSTASH_REDIS_REST_TOKEN'] ?? env['KV_REST_API_TOKEN'];
|
|
102
|
-
const redisUrl = env['KV_URL'] ?? env['REDIS_URL'];
|
|
103
|
-
const redisHost = env['REDIS_HOST'] ?? env['UPSTASH_HOST'];
|
|
104
|
-
const redisPassword = env['REDIS_PASSWORD'] ?? env['UPSTASH_PASSWORD'];
|
|
105
|
-
|
|
106
|
-
if (upstashUrl || redisUrl || redisHost || env['REDIS_PORT'] || redisPassword) {
|
|
107
|
-
cfg.redis = {
|
|
108
|
-
url: redisUrl,
|
|
109
|
-
host: redisHost,
|
|
110
|
-
port: env['REDIS_PORT'] ? parseInt(env['REDIS_PORT'], 10) : undefined,
|
|
111
|
-
password: redisPassword,
|
|
112
|
-
ssl: parseBool(env['REDIS_SSL']),
|
|
113
|
-
upstashUrl,
|
|
114
|
-
upstashToken,
|
|
115
|
-
};
|
|
116
|
-
}
|
|
117
|
-
|
|
118
|
-
// Langfuse
|
|
119
|
-
if (env['LANGFUSE_PUBLIC_KEY'] || env['LANGFUSE_SECRET_KEY']) {
|
|
120
|
-
cfg.langfuse = {
|
|
121
|
-
publicKey: env['LANGFUSE_PUBLIC_KEY'],
|
|
122
|
-
secretKey: env['LANGFUSE_SECRET_KEY'],
|
|
123
|
-
baseUrl: env['LANGFUSE_BASE_URL'] ?? env['LANGFUSE_HOST'],
|
|
124
|
-
};
|
|
125
|
-
}
|
|
126
|
-
|
|
127
|
-
// OpenAI
|
|
128
|
-
if (env['OPENAI_API_KEY']) {
|
|
129
|
-
cfg.openai = {
|
|
130
|
-
apiKey: env['OPENAI_API_KEY'],
|
|
131
|
-
model: env['OPENAI_MODEL'] ?? env['LLM_MODEL'],
|
|
132
|
-
};
|
|
133
|
-
}
|
|
134
|
-
|
|
135
|
-
// AWS
|
|
136
|
-
if (env['AWS_ACCESS_KEY_ID']) {
|
|
137
|
-
cfg.aws = {
|
|
138
|
-
accessKeyId: env['AWS_ACCESS_KEY_ID'],
|
|
139
|
-
secretAccessKey: env['AWS_SECRET_ACCESS_KEY'],
|
|
140
|
-
region: env['AWS_REGION'] ?? env['AWS_DEFAULT_REGION'],
|
|
141
|
-
};
|
|
142
|
-
}
|
|
143
|
-
|
|
144
|
-
// GitHub
|
|
145
|
-
if (env['GITHUB_TOKEN'] || env['GH_TOKEN']) {
|
|
146
|
-
cfg.github = {
|
|
147
|
-
token: env['GITHUB_TOKEN'] ?? env['GH_TOKEN'],
|
|
148
|
-
};
|
|
149
|
-
}
|
|
150
|
-
|
|
151
|
-
return cfg;
|
|
152
|
-
}
|
|
153
|
-
|
|
154
|
-
/**
|
|
155
|
-
* Read and assemble the full CoaiaConfig.
|
|
156
|
-
* Priority: env vars > .env file > coaia.json > defaults.
|
|
157
|
-
*/
|
|
158
|
-
export function readConfig(envPath?: string): CoaiaConfig {
|
|
159
|
-
// 1. Load .env (lowest priority file source)
|
|
160
|
-
for (const dotenvPath of findEnvFiles(envPath)) {
|
|
161
|
-
dotenv.config({ path: dotenvPath, override: false });
|
|
162
|
-
}
|
|
163
|
-
|
|
164
|
-
// 2. Load coaia.json
|
|
165
|
-
const configPath = findExistingConfig();
|
|
166
|
-
const jsonConfig = configPath ? loadJsonConfig(configPath) : {};
|
|
167
|
-
|
|
168
|
-
// 3. Env var overrides (highest priority)
|
|
169
|
-
const envCfg = envOverrides();
|
|
170
|
-
|
|
171
|
-
// 4. Merge: json < env
|
|
172
|
-
return mergeConfigs(jsonConfig, envCfg);
|
|
173
|
-
}
|
|
174
|
-
|
|
175
|
-
/** Singleton config instance, lazily loaded on first access. */
|
|
176
|
-
let _config: CoaiaConfig | null = null;
|
|
177
|
-
|
|
178
|
-
export function getConfig(): CoaiaConfig {
|
|
179
|
-
if (!_config) {
|
|
180
|
-
_config = readConfig();
|
|
181
|
-
}
|
|
182
|
-
return _config;
|
|
183
|
-
}
|
|
184
|
-
|
|
185
|
-
/** Reset singleton (useful in tests). */
|
|
186
|
-
export function resetConfig(): void {
|
|
187
|
-
_config = null;
|
|
188
|
-
}
|
|
189
|
-
|
|
190
|
-
export const config = new Proxy({} as CoaiaConfig, {
|
|
191
|
-
get(_target, prop: string) {
|
|
192
|
-
return getConfig()[prop];
|
|
193
|
-
},
|
|
194
|
-
ownKeys() {
|
|
195
|
-
return Object.keys(getConfig());
|
|
196
|
-
},
|
|
197
|
-
getOwnPropertyDescriptor(_target, prop: string) {
|
|
198
|
-
const cfg = getConfig();
|
|
199
|
-
if (prop in cfg) {
|
|
200
|
-
return { configurable: true, enumerable: true, value: cfg[prop] };
|
|
201
|
-
}
|
|
202
|
-
return undefined;
|
|
203
|
-
},
|
|
204
|
-
has(_target, prop: string) {
|
|
205
|
-
return prop in getConfig();
|
|
206
|
-
},
|
|
207
|
-
});
|
package/src/environment.ts
DELETED
|
@@ -1,171 +0,0 @@
|
|
|
1
|
-
// coaiajs/src/environment.ts — Environment management
|
|
2
|
-
// Parity with coaiapy's environment.py
|
|
3
|
-
|
|
4
|
-
import { readFileSync, writeFileSync, existsSync } from 'node:fs';
|
|
5
|
-
import { resolve, join } from 'node:path';
|
|
6
|
-
import { homedir } from 'node:os';
|
|
7
|
-
|
|
8
|
-
const ENV_FILENAME = '.coaia-env';
|
|
9
|
-
|
|
10
|
-
/** Well-known CoAIA environment variable names. */
|
|
11
|
-
const KNOWN_VARS = [
|
|
12
|
-
'COAIA_TRACE_ID',
|
|
13
|
-
'COAIA_SESSION_ID',
|
|
14
|
-
'COAIA_USER_ID',
|
|
15
|
-
'COAIA_PROJECT_ID',
|
|
16
|
-
'COAIA_ENV',
|
|
17
|
-
'COAIA_LOG_LEVEL',
|
|
18
|
-
'COAIA_CONFIG_PATH',
|
|
19
|
-
'COAIA_REDIS_URL',
|
|
20
|
-
'COAIA_PDE_DIR',
|
|
21
|
-
] as const;
|
|
22
|
-
|
|
23
|
-
export type KnownVar = (typeof KNOWN_VARS)[number];
|
|
24
|
-
|
|
25
|
-
export interface EnvStore {
|
|
26
|
-
[key: string]: string;
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
export class EnvironmentManager {
|
|
30
|
-
private store: EnvStore = {};
|
|
31
|
-
private filePath: string;
|
|
32
|
-
|
|
33
|
-
constructor(dir?: string) {
|
|
34
|
-
const baseDir = dir ?? process.cwd();
|
|
35
|
-
this.filePath = resolve(baseDir, ENV_FILENAME);
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
/** Initialize environment — load from file if it exists. */
|
|
39
|
-
init(): void {
|
|
40
|
-
if (existsSync(this.filePath)) {
|
|
41
|
-
this.load();
|
|
42
|
-
}
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
/** List all environment variables in the store. */
|
|
46
|
-
list(): EnvStore {
|
|
47
|
-
return { ...this.store };
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
/** Get a single variable value. */
|
|
51
|
-
get(key: string): string | undefined {
|
|
52
|
-
// Check store first, fall back to process.env
|
|
53
|
-
return this.store[key] ?? process.env[key];
|
|
54
|
-
}
|
|
55
|
-
|
|
56
|
-
/** Set an environment variable (in-memory + process.env). */
|
|
57
|
-
set(key: string, value: string): void {
|
|
58
|
-
this.store[key] = value;
|
|
59
|
-
process.env[key] = value;
|
|
60
|
-
}
|
|
61
|
-
|
|
62
|
-
/** Remove a variable from the store and process.env. */
|
|
63
|
-
unset(key: string): void {
|
|
64
|
-
delete this.store[key];
|
|
65
|
-
delete process.env[key];
|
|
66
|
-
}
|
|
67
|
-
|
|
68
|
-
/** Clear all stored variables. */
|
|
69
|
-
clear(): void {
|
|
70
|
-
for (const key of Object.keys(this.store)) {
|
|
71
|
-
delete process.env[key];
|
|
72
|
-
}
|
|
73
|
-
this.store = {};
|
|
74
|
-
}
|
|
75
|
-
|
|
76
|
-
/**
|
|
77
|
-
* Source variables into process.env (like `source .env`).
|
|
78
|
-
* Applies all stored vars to process.env.
|
|
79
|
-
*/
|
|
80
|
-
source(): void {
|
|
81
|
-
for (const [key, value] of Object.entries(this.store)) {
|
|
82
|
-
process.env[key] = value;
|
|
83
|
-
}
|
|
84
|
-
}
|
|
85
|
-
|
|
86
|
-
/** Save the current store to .coaia-env (JSON format). */
|
|
87
|
-
save(): void {
|
|
88
|
-
writeFileSync(this.filePath, JSON.stringify(this.store, null, 2), 'utf-8');
|
|
89
|
-
}
|
|
90
|
-
|
|
91
|
-
/** Save as .env format. */
|
|
92
|
-
saveAsEnv(outPath?: string): void {
|
|
93
|
-
const target = outPath ?? this.filePath.replace(/\.coaia-env$/, '.coaia.env');
|
|
94
|
-
const lines = Object.entries(this.store)
|
|
95
|
-
.map(([k, v]) => `${k}=${v}`)
|
|
96
|
-
.join('\n');
|
|
97
|
-
writeFileSync(target, lines + '\n', 'utf-8');
|
|
98
|
-
}
|
|
99
|
-
|
|
100
|
-
/** Load from .coaia-env file. Supports JSON and .env formats. */
|
|
101
|
-
private load(): void {
|
|
102
|
-
const raw = readFileSync(this.filePath, 'utf-8').trim();
|
|
103
|
-
|
|
104
|
-
// Try JSON first
|
|
105
|
-
if (raw.startsWith('{')) {
|
|
106
|
-
try {
|
|
107
|
-
this.store = JSON.parse(raw) as EnvStore;
|
|
108
|
-
return;
|
|
109
|
-
} catch {
|
|
110
|
-
// Fall through to .env parsing
|
|
111
|
-
}
|
|
112
|
-
}
|
|
113
|
-
|
|
114
|
-
// Parse .env format: KEY=VALUE lines
|
|
115
|
-
this.store = {};
|
|
116
|
-
for (const line of raw.split('\n')) {
|
|
117
|
-
const trimmed = line.trim();
|
|
118
|
-
if (!trimmed || trimmed.startsWith('#')) continue;
|
|
119
|
-
const eqIdx = trimmed.indexOf('=');
|
|
120
|
-
if (eqIdx === -1) continue;
|
|
121
|
-
const key = trimmed.slice(0, eqIdx).trim();
|
|
122
|
-
let value = trimmed.slice(eqIdx + 1).trim();
|
|
123
|
-
// Strip surrounding quotes
|
|
124
|
-
if (
|
|
125
|
-
(value.startsWith('"') && value.endsWith('"')) ||
|
|
126
|
-
(value.startsWith("'") && value.endsWith("'"))
|
|
127
|
-
) {
|
|
128
|
-
value = value.slice(1, -1);
|
|
129
|
-
}
|
|
130
|
-
this.store[key] = value;
|
|
131
|
-
}
|
|
132
|
-
}
|
|
133
|
-
|
|
134
|
-
/** Get the file path being used. */
|
|
135
|
-
getFilePath(): string {
|
|
136
|
-
return this.filePath;
|
|
137
|
-
}
|
|
138
|
-
|
|
139
|
-
/** Get well-known CoAIA variables that are currently set. */
|
|
140
|
-
getKnownVars(): Partial<Record<KnownVar, string>> {
|
|
141
|
-
const result: Partial<Record<KnownVar, string>> = {};
|
|
142
|
-
for (const key of KNOWN_VARS) {
|
|
143
|
-
const val = this.get(key);
|
|
144
|
-
if (val !== undefined) {
|
|
145
|
-
result[key] = val;
|
|
146
|
-
}
|
|
147
|
-
}
|
|
148
|
-
return result;
|
|
149
|
-
}
|
|
150
|
-
}
|
|
151
|
-
|
|
152
|
-
/** Create a default EnvironmentManager for the current directory. */
|
|
153
|
-
export function createEnvironment(dir?: string): EnvironmentManager {
|
|
154
|
-
const mgr = new EnvironmentManager(dir);
|
|
155
|
-
mgr.init();
|
|
156
|
-
return mgr;
|
|
157
|
-
}
|
|
158
|
-
|
|
159
|
-
/** Find and load environment from cwd or home. */
|
|
160
|
-
export function findEnvironment(): EnvironmentManager {
|
|
161
|
-
const cwdPath = resolve(process.cwd(), ENV_FILENAME);
|
|
162
|
-
if (existsSync(cwdPath)) {
|
|
163
|
-
return createEnvironment(process.cwd());
|
|
164
|
-
}
|
|
165
|
-
const homePath = join(homedir(), ENV_FILENAME);
|
|
166
|
-
if (existsSync(homePath)) {
|
|
167
|
-
return createEnvironment(homedir());
|
|
168
|
-
}
|
|
169
|
-
// Return empty manager for cwd
|
|
170
|
-
return new EnvironmentManager(process.cwd());
|
|
171
|
-
}
|
package/src/github.ts
DELETED
|
@@ -1,143 +0,0 @@
|
|
|
1
|
-
// coaiajs/src/github.ts — GitHub module
|
|
2
|
-
// Parity with coaiapy's cogh.py using @octokit/rest
|
|
3
|
-
|
|
4
|
-
import { Octokit } from '@octokit/rest';
|
|
5
|
-
import { getConfig } from './config.js';
|
|
6
|
-
|
|
7
|
-
let _client: Octokit | null = null;
|
|
8
|
-
|
|
9
|
-
function getOctokit(): Octokit {
|
|
10
|
-
if (!_client) {
|
|
11
|
-
const cfg = getConfig();
|
|
12
|
-
_client = new Octokit({
|
|
13
|
-
auth: cfg.github?.token ?? process.env['GITHUB_TOKEN'] ?? process.env['GH_TOKEN'],
|
|
14
|
-
});
|
|
15
|
-
}
|
|
16
|
-
return _client;
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
/** Reset client (testing). */
|
|
20
|
-
export function resetClient(): void {
|
|
21
|
-
_client = null;
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
export interface Issue {
|
|
25
|
-
number: number;
|
|
26
|
-
title: string;
|
|
27
|
-
state: string;
|
|
28
|
-
body: string | null;
|
|
29
|
-
labels: Array<{ name: string }>;
|
|
30
|
-
assignees: Array<{ login: string }>;
|
|
31
|
-
created_at: string;
|
|
32
|
-
updated_at: string;
|
|
33
|
-
html_url: string;
|
|
34
|
-
user: { login: string } | null;
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
export interface IssueComment {
|
|
38
|
-
id: number;
|
|
39
|
-
body: string;
|
|
40
|
-
user: { login: string } | null;
|
|
41
|
-
created_at: string;
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
/**
|
|
45
|
-
* List issues for a repository.
|
|
46
|
-
* Parity with coaiapy's cogh list_issues.
|
|
47
|
-
*/
|
|
48
|
-
export async function listIssues(
|
|
49
|
-
owner: string,
|
|
50
|
-
repo: string,
|
|
51
|
-
options?: {
|
|
52
|
-
state?: 'open' | 'closed' | 'all';
|
|
53
|
-
labels?: string;
|
|
54
|
-
per_page?: number;
|
|
55
|
-
page?: number;
|
|
56
|
-
},
|
|
57
|
-
): Promise<Issue[]> {
|
|
58
|
-
const client = getOctokit();
|
|
59
|
-
|
|
60
|
-
const response = await client.issues.listForRepo({
|
|
61
|
-
owner,
|
|
62
|
-
repo,
|
|
63
|
-
state: options?.state ?? 'open',
|
|
64
|
-
labels: options?.labels,
|
|
65
|
-
per_page: options?.per_page ?? 30,
|
|
66
|
-
page: options?.page ?? 1,
|
|
67
|
-
});
|
|
68
|
-
|
|
69
|
-
return response.data.map(mapIssue);
|
|
70
|
-
}
|
|
71
|
-
|
|
72
|
-
/**
|
|
73
|
-
* Get a single issue by number.
|
|
74
|
-
*/
|
|
75
|
-
export async function getIssue(
|
|
76
|
-
owner: string,
|
|
77
|
-
repo: string,
|
|
78
|
-
issueNumber: number,
|
|
79
|
-
): Promise<Issue> {
|
|
80
|
-
const client = getOctokit();
|
|
81
|
-
|
|
82
|
-
const response = await client.issues.get({
|
|
83
|
-
owner,
|
|
84
|
-
repo,
|
|
85
|
-
issue_number: issueNumber,
|
|
86
|
-
});
|
|
87
|
-
|
|
88
|
-
return mapIssue(response.data);
|
|
89
|
-
}
|
|
90
|
-
|
|
91
|
-
/**
|
|
92
|
-
* Get comments for an issue.
|
|
93
|
-
*/
|
|
94
|
-
export async function getIssueComments(
|
|
95
|
-
owner: string,
|
|
96
|
-
repo: string,
|
|
97
|
-
issueNumber: number,
|
|
98
|
-
): Promise<IssueComment[]> {
|
|
99
|
-
const client = getOctokit();
|
|
100
|
-
|
|
101
|
-
const response = await client.issues.listComments({
|
|
102
|
-
owner,
|
|
103
|
-
repo,
|
|
104
|
-
issue_number: issueNumber,
|
|
105
|
-
});
|
|
106
|
-
|
|
107
|
-
return response.data.map((c) => ({
|
|
108
|
-
id: c.id,
|
|
109
|
-
body: c.body ?? '',
|
|
110
|
-
user: c.user ? { login: c.user.login } : null,
|
|
111
|
-
created_at: c.created_at,
|
|
112
|
-
}));
|
|
113
|
-
}
|
|
114
|
-
|
|
115
|
-
function mapIssue(data: Record<string, unknown>): Issue {
|
|
116
|
-
const d = data as {
|
|
117
|
-
number: number;
|
|
118
|
-
title: string;
|
|
119
|
-
state: string;
|
|
120
|
-
body: string | null;
|
|
121
|
-
labels: Array<{ name?: string } | string>;
|
|
122
|
-
assignees: Array<{ login: string }> | null;
|
|
123
|
-
created_at: string;
|
|
124
|
-
updated_at: string;
|
|
125
|
-
html_url: string;
|
|
126
|
-
user: { login: string } | null;
|
|
127
|
-
};
|
|
128
|
-
|
|
129
|
-
return {
|
|
130
|
-
number: d.number,
|
|
131
|
-
title: d.title,
|
|
132
|
-
state: d.state,
|
|
133
|
-
body: d.body,
|
|
134
|
-
labels: (d.labels ?? []).map((l) =>
|
|
135
|
-
typeof l === 'string' ? { name: l } : { name: l.name ?? '' },
|
|
136
|
-
),
|
|
137
|
-
assignees: (d.assignees ?? []).map((a) => ({ login: a.login })),
|
|
138
|
-
created_at: d.created_at,
|
|
139
|
-
updated_at: d.updated_at,
|
|
140
|
-
html_url: d.html_url,
|
|
141
|
-
user: d.user ? { login: d.user.login } : null,
|
|
142
|
-
};
|
|
143
|
-
}
|
package/src/index.ts
DELETED
|
@@ -1,82 +0,0 @@
|
|
|
1
|
-
// coaiajs/src/index.ts — Published package entry point
|
|
2
|
-
|
|
3
|
-
export {
|
|
4
|
-
findExistingConfig,
|
|
5
|
-
mergeConfigs,
|
|
6
|
-
readConfig,
|
|
7
|
-
getConfig,
|
|
8
|
-
resetConfig,
|
|
9
|
-
config,
|
|
10
|
-
} from './config.js';
|
|
11
|
-
|
|
12
|
-
export {
|
|
13
|
-
getClient as getRedisClient,
|
|
14
|
-
tash,
|
|
15
|
-
fetch,
|
|
16
|
-
del,
|
|
17
|
-
keys,
|
|
18
|
-
exists,
|
|
19
|
-
disconnect,
|
|
20
|
-
resetClient as resetRedisClient,
|
|
21
|
-
} from './redis.js';
|
|
22
|
-
|
|
23
|
-
export {
|
|
24
|
-
llm,
|
|
25
|
-
transcribeAudio,
|
|
26
|
-
generateImage,
|
|
27
|
-
abstractProcess,
|
|
28
|
-
resetClient as resetLlmClient,
|
|
29
|
-
} from './llm.js';
|
|
30
|
-
|
|
31
|
-
export {
|
|
32
|
-
synthesize,
|
|
33
|
-
resetClient as resetAudioClient,
|
|
34
|
-
} from './audio.js';
|
|
35
|
-
|
|
36
|
-
export {
|
|
37
|
-
listIssues,
|
|
38
|
-
getIssue,
|
|
39
|
-
getIssueComments,
|
|
40
|
-
resetClient as resetGithubClient,
|
|
41
|
-
} from './github.js';
|
|
42
|
-
|
|
43
|
-
export {
|
|
44
|
-
EnvironmentManager,
|
|
45
|
-
createEnvironment,
|
|
46
|
-
findEnvironment,
|
|
47
|
-
} from './environment.js';
|
|
48
|
-
|
|
49
|
-
export * as langfuse from './langfuse/index.js';
|
|
50
|
-
export * as narrative from './narrative/index.js';
|
|
51
|
-
export * as pde from './pde/index.js';
|
|
52
|
-
export * as planning from './planning/index.js';
|
|
53
|
-
export * as pipeline from './pipeline/index.js';
|
|
54
|
-
|
|
55
|
-
export type {
|
|
56
|
-
Entity,
|
|
57
|
-
EntityMetadata,
|
|
58
|
-
Relation,
|
|
59
|
-
RelationMetadata,
|
|
60
|
-
KnowledgeGraph,
|
|
61
|
-
McpToolResult,
|
|
62
|
-
PrimaryIntent,
|
|
63
|
-
SecondaryIntent,
|
|
64
|
-
ContextRequirements,
|
|
65
|
-
ExpectedOutputs,
|
|
66
|
-
DirectionItem,
|
|
67
|
-
DirectionMap,
|
|
68
|
-
ActionItem,
|
|
69
|
-
AmbiguityFlag,
|
|
70
|
-
DecompositionResult,
|
|
71
|
-
StoredDecomposition,
|
|
72
|
-
DecompositionOptions,
|
|
73
|
-
PdeSession,
|
|
74
|
-
StructuralElement,
|
|
75
|
-
StructuralTensionPlan,
|
|
76
|
-
ScoreCategory,
|
|
77
|
-
ScoreConfig,
|
|
78
|
-
PipelineVariable,
|
|
79
|
-
PipelineStep,
|
|
80
|
-
PipelineTemplate,
|
|
81
|
-
CoaiaConfig,
|
|
82
|
-
} from './types.js';
|
package/src/langfuse/client.ts
DELETED
|
@@ -1,105 +0,0 @@
|
|
|
1
|
-
// coaiajs/src/langfuse/client.ts — Langfuse REST client
|
|
2
|
-
// Parity with cofuse.py's direct REST approach (no SDK dependency for API calls)
|
|
3
|
-
|
|
4
|
-
import { getConfig } from '../config.js';
|
|
5
|
-
|
|
6
|
-
export interface IngestionEvent {
|
|
7
|
-
id: string;
|
|
8
|
-
timestamp: string;
|
|
9
|
-
type: 'trace-create' | 'observation-create' | 'score-create' | 'sdk-log';
|
|
10
|
-
body: Record<string, unknown>;
|
|
11
|
-
}
|
|
12
|
-
|
|
13
|
-
export interface LangfuseClientConfig {
|
|
14
|
-
publicKey?: string;
|
|
15
|
-
secretKey?: string;
|
|
16
|
-
baseUrl?: string;
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
export class LangfuseClient {
|
|
20
|
-
private publicKey: string;
|
|
21
|
-
private secretKey: string;
|
|
22
|
-
private baseUrl: string;
|
|
23
|
-
|
|
24
|
-
constructor(config?: LangfuseClientConfig) {
|
|
25
|
-
const appConfig = getConfig();
|
|
26
|
-
this.publicKey = config?.publicKey ?? appConfig.langfuse?.publicKey ?? '';
|
|
27
|
-
this.secretKey = config?.secretKey ?? appConfig.langfuse?.secretKey ?? '';
|
|
28
|
-
this.baseUrl = (config?.baseUrl ?? appConfig.langfuse?.baseUrl ?? 'https://cloud.langfuse.com').replace(/\/+$/, '');
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
private getAuthHeader(): string {
|
|
32
|
-
const credentials = Buffer.from(`${this.publicKey}:${this.secretKey}`).toString('base64');
|
|
33
|
-
return `Basic ${credentials}`;
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
async request<T = unknown>(method: string, path: string, body?: unknown): Promise<T> {
|
|
37
|
-
const url = `${this.baseUrl}${path}`;
|
|
38
|
-
const headers: Record<string, string> = {
|
|
39
|
-
'Authorization': this.getAuthHeader(),
|
|
40
|
-
'Content-Type': 'application/json',
|
|
41
|
-
};
|
|
42
|
-
|
|
43
|
-
const init: RequestInit = { method, headers };
|
|
44
|
-
if (body !== undefined) {
|
|
45
|
-
init.body = JSON.stringify(body);
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
const response = await fetch(url, init);
|
|
49
|
-
const text = await response.text();
|
|
50
|
-
|
|
51
|
-
if (!response.ok) {
|
|
52
|
-
let detail: string;
|
|
53
|
-
try {
|
|
54
|
-
detail = JSON.stringify(JSON.parse(text), null, 2);
|
|
55
|
-
} catch {
|
|
56
|
-
detail = text;
|
|
57
|
-
}
|
|
58
|
-
throw new LangfuseApiError(
|
|
59
|
-
`Langfuse API error ${response.status}: ${detail}`,
|
|
60
|
-
response.status,
|
|
61
|
-
detail,
|
|
62
|
-
);
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
if (!text) return undefined as T;
|
|
66
|
-
return JSON.parse(text) as T;
|
|
67
|
-
}
|
|
68
|
-
|
|
69
|
-
async ingest(events: IngestionEvent[]): Promise<void> {
|
|
70
|
-
await this.request('POST', '/api/public/ingestion', { batch: events });
|
|
71
|
-
}
|
|
72
|
-
|
|
73
|
-
getBaseUrl(): string {
|
|
74
|
-
return this.baseUrl;
|
|
75
|
-
}
|
|
76
|
-
}
|
|
77
|
-
|
|
78
|
-
export class LangfuseApiError extends Error {
|
|
79
|
-
constructor(
|
|
80
|
-
message: string,
|
|
81
|
-
public readonly statusCode: number,
|
|
82
|
-
public readonly detail: string,
|
|
83
|
-
) {
|
|
84
|
-
super(message);
|
|
85
|
-
this.name = 'LangfuseApiError';
|
|
86
|
-
}
|
|
87
|
-
}
|
|
88
|
-
|
|
89
|
-
// Singleton with lazy init
|
|
90
|
-
let _client: LangfuseClient | null = null;
|
|
91
|
-
|
|
92
|
-
export function getClient(config?: LangfuseClientConfig): LangfuseClient {
|
|
93
|
-
if (!_client) {
|
|
94
|
-
_client = new LangfuseClient(config);
|
|
95
|
-
}
|
|
96
|
-
return _client;
|
|
97
|
-
}
|
|
98
|
-
|
|
99
|
-
export function resetClient(): void {
|
|
100
|
-
_client = null;
|
|
101
|
-
}
|
|
102
|
-
|
|
103
|
-
export function nowISO(): string {
|
|
104
|
-
return new Date().toISOString();
|
|
105
|
-
}
|