osagent 0.1.84 → 0.1.86

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/README.md CHANGED
@@ -210,7 +210,7 @@ Episodes are stored locally in `~/.osagent/episodes/`.
210
210
 
211
211
  ### Configuration
212
212
 
213
- OS Agent stores its configuration in `~/.osagent/`:
213
+ OS Agent stores its configuration in `~/.osagent/` (created automatically on first run):
214
214
 
215
215
  ```
216
216
  ~/.osagent/
@@ -219,8 +219,7 @@ OS Agent stores its configuration in `~/.osagent/`:
219
219
  ├── commands/ # Custom slash commands (.toml)
220
220
  ├── skills/ # Custom skill plugins (.yaml)
221
221
  ├── prompts/ # Custom prompts
222
- ├── episodes/ # Episodic memory storage
223
- └── system.md # Custom system prompt
222
+ └── episodes/ # Episodic memory storage
224
223
  ```
225
224
 
226
225
  ### Custom Agents
@@ -322,6 +321,17 @@ packages/
322
321
 
323
322
  ## Recent Updates
324
323
 
324
+ ### v0.1.86 - Auto Project Context
325
+ - Automatic project context injection on first prompt
326
+ - When no OSAGENT.md exists, AI auto-explores project structure before responding
327
+ - No manual `/init` required for casual usage
328
+
329
+ ### v0.1.85 - Security & Stability Fixes
330
+ - Timer now only counts active work time (stops when idle)
331
+ - Fixed command injection vulnerability in git co-author feature
332
+ - Fixed symlink bypass in path validation
333
+ - Fixed VimModeContext re-render loop
334
+
325
335
  ### v0.1.83 - Enhanced Doctor Command
326
336
  - Added enhanced installation diagnostics to `/doctor`
327
337
  - Shows installation method (npm-global, homebrew, native, source)
@@ -146587,7 +146587,7 @@ function createContentGeneratorConfig(config2, authType, generationConfig) {
146587
146587
  };
146588
146588
  }
146589
146589
  async function createContentGenerator(config2, gcConfig, sessionId2, isInitialAuth) {
146590
- const version3 = "0.1.84";
146590
+ const version3 = "0.1.86";
146591
146591
  const userAgent2 = `OSAgent/${version3} (${process.platform}; ${process.arch})`;
146592
146592
  const baseHeaders = {
146593
146593
  "User-Agent": userAgent2
@@ -161283,9 +161283,20 @@ ${result.output}`;
161283
161283
  if (!gitCommitPattern.test(command2.trim())) {
161284
161284
  return command2;
161285
161285
  }
161286
+ const sanitizeName = /* @__PURE__ */ __name((name3) => {
161287
+ return name3.replace(/[\n\r"'`$\\<>|;&]/g, "").trim().slice(0, 100);
161288
+ }, "sanitizeName");
161289
+ const sanitizeEmail = /* @__PURE__ */ __name((email2) => {
161290
+ return email2.replace(/[\n\r"'`$\\<>|;&\s]/g, "").trim().slice(0, 254);
161291
+ }, "sanitizeEmail");
161292
+ const safeName = sanitizeName(gitCoAuthorSettings.name ?? "");
161293
+ const safeEmail = sanitizeEmail(gitCoAuthorSettings.email ?? "");
161294
+ if (!safeName || !safeEmail) {
161295
+ return command2;
161296
+ }
161286
161297
  const coAuthor = `
161287
161298
 
161288
- Co-authored-by: ${gitCoAuthorSettings.name} <${gitCoAuthorSettings.email}>`;
161299
+ Co-authored-by: ${safeName} <${safeEmail}>`;
161289
161300
  const messagePattern = /(-m\s+)(['"])((?:\\.|[^\\])*?)(\2)/;
161290
161301
  const match2 = command2.match(messagePattern);
161291
161302
  if (match2) {
@@ -161360,10 +161371,20 @@ Co-authored-by: ${gitCoAuthorSettings.name} <${gitCoAuthorSettings.email}>`;
161360
161371
  if (!path18.isAbsolute(params.directory)) {
161361
161372
  return "Directory must be an absolute path.";
161362
161373
  }
161363
- const normalizedDir = path18.resolve(params.directory);
161374
+ let normalizedDir;
161375
+ try {
161376
+ normalizedDir = fs21.realpathSync(params.directory);
161377
+ } catch {
161378
+ normalizedDir = path18.resolve(params.directory);
161379
+ }
161364
161380
  const workspaceDirs = this.config.getWorkspaceContext().getDirectories();
161365
161381
  const isWithinWorkspace = workspaceDirs.some((wsDir) => {
161366
- const normalizedWsDir = path18.resolve(wsDir);
161382
+ let normalizedWsDir;
161383
+ try {
161384
+ normalizedWsDir = fs21.realpathSync(wsDir);
161385
+ } catch {
161386
+ normalizedWsDir = path18.resolve(wsDir);
161387
+ }
161367
161388
  return normalizedDir === normalizedWsDir || normalizedDir.startsWith(normalizedWsDir + path18.sep);
161368
161389
  });
161369
161390
  if (!isWithinWorkspace) {
@@ -265306,7 +265327,7 @@ var require_backend = __commonJS({
265306
265327
  return [b, function() {
265307
265328
  }];
265308
265329
  }, "useReducer"),
265309
- useRef: /* @__PURE__ */ __name(function useRef36(a) {
265330
+ useRef: /* @__PURE__ */ __name(function useRef37(a) {
265310
265331
  var b = C();
265311
265332
  a = null !== b ? b.memoizedState : {
265312
265333
  current: a
@@ -335543,7 +335564,7 @@ __name(getPackageJson, "getPackageJson");
335543
335564
  // packages/cli/src/utils/version.ts
335544
335565
  async function getCliVersion() {
335545
335566
  const pkgJson = await getPackageJson();
335546
- return "0.1.84";
335567
+ return "0.1.86";
335547
335568
  }
335548
335569
  __name(getCliVersion, "getCliVersion");
335549
335570
 
@@ -339745,8 +339766,8 @@ var formatDuration = /* @__PURE__ */ __name((milliseconds) => {
339745
339766
 
339746
339767
  // packages/cli/src/generated/git-commit.ts
339747
339768
  init_esbuild_shims();
339748
- var GIT_COMMIT_INFO2 = "2866a59";
339749
- var CLI_VERSION2 = "0.1.84";
339769
+ var GIT_COMMIT_INFO2 = "c5e8879";
339770
+ var CLI_VERSION2 = "0.1.86";
339750
339771
 
339751
339772
  // packages/cli/src/utils/systemInfo.ts
339752
339773
  async function getNpmVersion() {
@@ -376370,25 +376391,32 @@ var VimModeProvider = /* @__PURE__ */ __name(({
376370
376391
  }) => {
376371
376392
  const initialVimEnabled = settings.merged.general?.vimMode ?? false;
376372
376393
  const [vimEnabled, setVimEnabled] = (0, import_react81.useState)(initialVimEnabled);
376373
- const [vimMode, setVimMode] = (0, import_react81.useState)(
376394
+ const [vimMode, setVimModeState] = (0, import_react81.useState)(
376374
376395
  initialVimEnabled ? "NORMAL" : "INSERT"
376375
376396
  );
376397
+ const vimEnabledRef = (0, import_react81.useRef)(vimEnabled);
376398
+ (0, import_react81.useEffect)(() => {
376399
+ vimEnabledRef.current = vimEnabled;
376400
+ }, [vimEnabled]);
376376
376401
  (0, import_react81.useEffect)(() => {
376377
376402
  const enabled = settings.merged.general?.vimMode ?? false;
376378
376403
  setVimEnabled(enabled);
376379
376404
  if (enabled) {
376380
- setVimMode("NORMAL");
376405
+ setVimModeState("NORMAL");
376381
376406
  }
376382
376407
  }, [settings.merged.general?.vimMode]);
376408
+ const setVimMode = (0, import_react81.useCallback)((mode) => {
376409
+ setVimModeState(mode);
376410
+ }, []);
376383
376411
  const toggleVimEnabled = (0, import_react81.useCallback)(async () => {
376384
- const newValue = !vimEnabled;
376412
+ const newValue = !vimEnabledRef.current;
376385
376413
  setVimEnabled(newValue);
376386
376414
  if (newValue) {
376387
- setVimMode("NORMAL");
376415
+ setVimModeState("NORMAL");
376388
376416
  }
376389
376417
  await settings.setValue("User" /* User */, "general.vimMode", newValue);
376390
376418
  return newValue;
376391
- }, [vimEnabled, settings]);
376419
+ }, [settings]);
376392
376420
  const value = (0, import_react81.useMemo)(() => ({
376393
376421
  vimEnabled,
376394
376422
  vimMode,
@@ -391846,13 +391874,24 @@ var AppContainer = /* @__PURE__ */ __name((props) => {
391846
391874
  currentPrompt,
391847
391875
  tokenUsage
391848
391876
  });
391877
+ const hasAutoContextInjected = (0, import_react154.useRef)(false);
391849
391878
  const handleFinalSubmit = (0, import_react154.useCallback)(
391850
391879
  (submittedValue) => {
391851
391880
  setCurrentPrompt(submittedValue);
391852
391881
  setPromptCount((prev) => prev + 1);
391853
- addMessage(submittedValue);
391882
+ const isSlashCommand2 = submittedValue.trim().startsWith("/");
391883
+ const needsAutoContext = !isSlashCommand2 && !hasAutoContextInjected.current && OSAMdFileCount === 0 && submittedValue.trim().length > 0;
391884
+ if (needsAutoContext) {
391885
+ hasAutoContextInjected.current = true;
391886
+ const enhancedPrompt = `Before responding to my request, please quickly explore this project to understand its structure (check package.json, README, main source directories). This will help you give better answers.
391887
+
391888
+ My request: ${submittedValue}`;
391889
+ addMessage(enhancedPrompt);
391890
+ } else {
391891
+ addMessage(submittedValue);
391892
+ }
391854
391893
  },
391855
- [addMessage]
391894
+ [addMessage, OSAMdFileCount]
391856
391895
  );
391857
391896
  const {
391858
391897
  welcomeBackInfo,