@almadar/workspace 0.2.5 → 0.3.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.
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,2 @@
1
+ import type { AccountService, OpenAccountOptions } from './types.js';
2
+ export declare function openAccount(opts?: OpenAccountOptions): Promise<AccountService>;
package/dist/index.d.ts CHANGED
@@ -7,6 +7,7 @@
7
7
  * `src/internal/`.
8
8
  */
9
9
  export { openWorkspace } from './open-workspace.js';
10
- export type { WorkspaceService, WorkspaceObserver, WorkspaceWriteEvent, OpenWorkspaceOptions, RestoreBackend, GitHubConfig, GitStatusInfo, FileTreeNode, } from './types.js';
10
+ export { openAccount } from './account.js';
11
+ export type { WorkspaceService, WorkspaceObserver, WorkspaceWriteEvent, WorkspaceWatchEvent, OpenWorkspaceOptions, RestoreBackend, GitHubConfig, GitStatusInfo, FileTreeNode, AccountService, AccountConfig, ProviderCredential, AccountIdentity, OpenAccountOptions, } from './types.js';
11
12
  export type { WorkspaceIndex, EmbedderPort, ResolveResult, ResolveOptions, TraitRefEmit, WorkspaceIndexStats, OrbitalIndexEntry, ExtraTraitIdentity, RetrievalResult, RetrievalOptions, RecentlyEditedOptions, EventEdge, EntityBinding, RuleBinding, RecencyEntry, IntentMaps, ComposedMaps, BM25Document, BM25Table, BM25Options, WorkspaceIndexManifest, } from './workspace-index/types.js';
12
13
  export { DEFAULT_COERCION_THRESHOLD, DEFAULT_RETRIEVAL_TOP_K, RRF_K, WORKSPACE_INDEX_SCHEMA_VERSION, } from './workspace-index/types.js';
package/dist/index.js CHANGED
@@ -3,6 +3,7 @@ import fs from 'fs';
3
3
  import { execFile } from 'child_process';
4
4
  import { randomBytes, createHash } from 'crypto';
5
5
  import { EmbeddingClient } from '@almadar/llm';
6
+ import os from 'os';
6
7
 
7
8
  // src/open-workspace.ts
8
9
  var LocalBackend = class {
@@ -46,6 +47,27 @@ var LocalBackend = class {
46
47
  await fs.promises.mkdir(path2.dirname(dstAbs), { recursive: true });
47
48
  await fs.promises.rename(srcAbs, dstAbs);
48
49
  }
50
+ async chmod(absPath, mode) {
51
+ await fs.promises.chmod(absPath, mode);
52
+ }
53
+ watch(absPath, onChange) {
54
+ let watcher;
55
+ let timer;
56
+ try {
57
+ watcher = fs.watch(absPath, (eventType) => {
58
+ if (timer) clearTimeout(timer);
59
+ timer = setTimeout(() => {
60
+ timer = void 0;
61
+ onChange(eventType === "rename" ? "rename" : "change");
62
+ }, 75);
63
+ });
64
+ } catch {
65
+ }
66
+ return () => {
67
+ if (timer) clearTimeout(timer);
68
+ watcher?.close();
69
+ };
70
+ }
49
71
  };
50
72
 
51
73
  // src/internal/backends/memory.ts
@@ -144,6 +166,12 @@ var MemoryBackend = class {
144
166
  this.dirs.add(newDir);
145
167
  }
146
168
  }
169
+ async chmod() {
170
+ }
171
+ watch() {
172
+ return () => {
173
+ };
174
+ }
147
175
  // Test helpers
148
176
  getAll() {
149
177
  return new Map(this.files);
@@ -732,8 +760,8 @@ function tokenizeSpec(spec) {
732
760
  for (const p of pages) {
733
761
  const obj = asJsonObject2(p);
734
762
  if (!obj) continue;
735
- const path9 = obj["path"];
736
- if (typeof path9 === "string") pushTokens(tokens, path9);
763
+ const path10 = obj["path"];
764
+ if (typeof path10 === "string") pushTokens(tokens, path10);
737
765
  }
738
766
  }
739
767
  const ruleOverlay = asJsonObject2(params["ruleOverlay"]);
@@ -2043,6 +2071,10 @@ var WorkspaceServiceImpl = class {
2043
2071
  subscribe(observer) {
2044
2072
  return this.sinks.subscribe(observer);
2045
2073
  }
2074
+ watch(relPath, onChange) {
2075
+ const abs = sandboxedPath(this.workDir, relPath);
2076
+ return this.backend.watch(abs, (kind) => onChange({ relPath, kind }));
2077
+ }
2046
2078
  // === Disposal ===
2047
2079
  async dispose() {
2048
2080
  const pending = Array.from(this.writeQueue.values());
@@ -2160,28 +2192,31 @@ async function openWorkspaceInternal(opts) {
2160
2192
  const backend = opts.backend === "memory" ? new MemoryBackend() : new LocalBackend();
2161
2193
  const sinks = new SinkManager();
2162
2194
  const resolved = await resolveLifecycle(backend, opts);
2163
- await ensureSkeleton(backend, resolved.workDir);
2164
- await writeMintTemplatesIfMissing(
2165
- backend,
2166
- resolved.workDir,
2167
- opts.userId,
2168
- opts.projectName ?? "Untitled",
2169
- resolved.appId
2170
- );
2171
- if (resolved.appId !== void 0) {
2172
- const existing = readAppMarker(backend, resolved.workDir);
2173
- if (!existing || existing.appId !== resolved.appId) {
2174
- const marker = {
2175
- appId: resolved.appId,
2176
- userId: opts.userId,
2177
- createdAt: existing?.createdAt ?? Date.now()
2178
- };
2179
- if (opts.github?.repoUrl) marker.repoUrl = opts.github.repoUrl;
2180
- await writeAppMarker(backend, resolved.workDir, marker);
2195
+ const bare = opts.bare === true && opts.adopt !== void 0;
2196
+ if (!bare) {
2197
+ await ensureSkeleton(backend, resolved.workDir);
2198
+ await writeMintTemplatesIfMissing(
2199
+ backend,
2200
+ resolved.workDir,
2201
+ opts.userId,
2202
+ opts.projectName ?? "Untitled",
2203
+ resolved.appId
2204
+ );
2205
+ if (resolved.appId !== void 0) {
2206
+ const existing = readAppMarker(backend, resolved.workDir);
2207
+ if (!existing || existing.appId !== resolved.appId) {
2208
+ const marker = {
2209
+ appId: resolved.appId,
2210
+ userId: opts.userId,
2211
+ createdAt: existing?.createdAt ?? Date.now()
2212
+ };
2213
+ if (opts.github?.repoUrl) marker.repoUrl = opts.github.repoUrl;
2214
+ await writeAppMarker(backend, resolved.workDir, marker);
2215
+ }
2181
2216
  }
2182
2217
  }
2183
2218
  let git;
2184
- if (opts.github && opts.backend !== "memory") {
2219
+ if (!bare && opts.github && opts.backend !== "memory") {
2185
2220
  git = await ensureGitInit(backend, resolved.workDir);
2186
2221
  }
2187
2222
  const service = new WorkspaceServiceImpl({
@@ -2193,7 +2228,9 @@ async function openWorkspaceInternal(opts) {
2193
2228
  git,
2194
2229
  github: opts.github
2195
2230
  });
2196
- await service.index.warm();
2231
+ if (!bare) {
2232
+ await service.index.warm();
2233
+ }
2197
2234
  return service;
2198
2235
  }
2199
2236
  async function resolveLifecycle(backend, opts) {
@@ -2225,7 +2262,89 @@ async function resolveLifecycle(backend, opts) {
2225
2262
  const workDir = mintSessionDir(opts.root, opts.userId);
2226
2263
  return { workDir, appId: opts.appId };
2227
2264
  }
2265
+ var ACCOUNT_DIR = ".almadar";
2266
+ var CONFIG_FILE = "config.json";
2267
+ var CREDENTIALS_FILE = "credentials.json";
2268
+ var ACCOUNT_FILE = "account.json";
2269
+ var SECRET_MODE = 384;
2270
+ var DEFAULT_CONFIG = {
2271
+ schemaVersion: 1,
2272
+ defaultProvider: "deepseek",
2273
+ defaultModel: "deepseek-v4-flash",
2274
+ autonomy: "balanced",
2275
+ source: "local"
2276
+ };
2277
+ async function openAccount(opts = {}) {
2278
+ const home = opts.home ?? os.homedir();
2279
+ const root = path2.join(home, ACCOUNT_DIR);
2280
+ const backend = opts.backend === "memory" ? new MemoryBackend() : new LocalBackend();
2281
+ const file = (name) => path2.join(root, name);
2282
+ async function readJson(name) {
2283
+ const p = file(name);
2284
+ if (!backend.exists(p)) return null;
2285
+ const raw = await backend.readFile(p);
2286
+ if (raw.trim().length === 0) return null;
2287
+ return JSON.parse(raw);
2288
+ }
2289
+ async function getConfig() {
2290
+ const stored = await readJson(CONFIG_FILE);
2291
+ return stored ? { ...DEFAULT_CONFIG, ...stored } : { ...DEFAULT_CONFIG };
2292
+ }
2293
+ async function setConfig(patch) {
2294
+ const next = { ...await getConfig(), ...patch };
2295
+ await backend.writeFile(file(CONFIG_FILE), JSON.stringify(next, null, 2));
2296
+ }
2297
+ async function readCredentials() {
2298
+ return await readJson(CREDENTIALS_FILE) ?? {};
2299
+ }
2300
+ async function writeCredentials(creds) {
2301
+ const p = file(CREDENTIALS_FILE);
2302
+ await backend.writeFile(p, JSON.stringify(creds, null, 2));
2303
+ await backend.chmod(p, SECRET_MODE);
2304
+ }
2305
+ return {
2306
+ root,
2307
+ getConfig,
2308
+ setConfig,
2309
+ async getCredential(provider) {
2310
+ return (await readCredentials())[provider] ?? null;
2311
+ },
2312
+ async setCredential(provider, cred) {
2313
+ const creds = await readCredentials();
2314
+ creds[provider] = cred;
2315
+ await writeCredentials(creds);
2316
+ },
2317
+ async listCredentialedProviders() {
2318
+ return Object.keys(await readCredentials());
2319
+ },
2320
+ async readAccount() {
2321
+ return readJson(ACCOUNT_FILE);
2322
+ },
2323
+ async writeAccount(identity) {
2324
+ await backend.writeFile(file(ACCOUNT_FILE), JSON.stringify(identity, null, 2));
2325
+ },
2326
+ async resolveProviderConfig(provider) {
2327
+ const creds = await readCredentials();
2328
+ const cred = creds[provider];
2329
+ if (!cred) return null;
2330
+ const cfg = await getConfig();
2331
+ const override = cfg.providers?.[provider];
2332
+ return {
2333
+ apiKey: cred.apiKey,
2334
+ ...override?.baseUrl ? { baseUrl: override.baseUrl } : {},
2335
+ defaultModel: override?.model ?? cfg.defaultModel
2336
+ };
2337
+ },
2338
+ async isConfigured() {
2339
+ const cfg = await getConfig();
2340
+ if (!cfg.setupCompletedAt) return false;
2341
+ return Object.keys(await readCredentials()).length > 0;
2342
+ },
2343
+ async dispose() {
2344
+ }
2345
+ };
2346
+ }
2228
2347
 
2229
- export { DEFAULT_COERCION_THRESHOLD, DEFAULT_RETRIEVAL_TOP_K, RRF_K, WORKSPACE_INDEX_SCHEMA_VERSION, openWorkspace };
2348
+ export { DEFAULT_COERCION_THRESHOLD, DEFAULT_RETRIEVAL_TOP_K, RRF_K, WORKSPACE_INDEX_SCHEMA_VERSION, openAccount, openWorkspace };
2230
2349
  //# sourceMappingURL=index.js.map
2231
2350
  //# sourceMappingURL=index.js.map